Board Game Arena tournoidoc139_br http:///Degemer MediaWiki 1.39.0 first-letter Media Dibar Kaozeal Implijer Kaozeadenn Implijer Board Game Arena Kaozeadenn Board Game Arena Restr Kaozeadenn Restr MediaWiki Kaozeadenn MediaWiki Patrom Kaozeadenn Patrom Skoazell Kaozeadenn Skoazell Rummad Kaozeadenn Rummad Main Page 0 1 1 2012-01-05T15:36:33Z MediaWiki default 0 wikitext text/x-wiki '''MediaWiki has been successfully installed.''' Consult the [//meta.wikimedia.org/wiki/Help:Contents User's Guide] for information on using the wiki software. == Getting started == * [//www.mediawiki.org/wiki/Manual:Configuration_settings Configuration settings list] * [//www.mediawiki.org/wiki/Manual:FAQ MediaWiki FAQ] * [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce MediaWiki release mailing list] b7a3846f2c55072191227d89a3204fe379288fee 6 1 2012-01-23T08:20:44Z Sourisdudesert 1 Redirected page to [[Help]] wikitext text/x-wiki #REDIRECT [[Help]] 716110d80c64acdd324d04dd290c1bffae7bce06 MediaWiki:Sidebar 8 2 2 2012-01-06T14:15:59Z Sourisdudesert 1 Created page with " * navigation ** http://boardgamearena.com|BoardGameArena.com ** mainpage|mainpage-description ** recentchanges-url|recentchanges * SEARCH * TOOLBOX * LANGUAGES" wikitext text/x-wiki * navigation ** http://boardgamearena.com|BoardGameArena.com ** mainpage|mainpage-description ** recentchanges-url|recentchanges * SEARCH * TOOLBOX * LANGUAGES bd8432e95416d227d9bca445c1f77a70aee1fbec Faq 0 3 3 2012-01-20T20:48:59Z Sourisdudesert 1 Created page with " test [[File:Reputation_down.png]]" wikitext text/x-wiki test [[File:Reputation_down.png]] 7b93a95fc5cc35ff8637c12da14176e1205f1e01 4 3 2012-01-20T21:10:48Z Sourisdudesert 1 wikitext text/x-wiki test [[File:Reputation_down.png]] http://en.wikipedia.org/upload/b/bc/Wiki.png 9195da8cff4846394bfa49361b55be1597869f51 5 4 2012-01-20T21:11:12Z Sourisdudesert 1 wikitext text/x-wiki test [[File:Reputation_down.png]] http://en.wikipedia.org/upload/b/bc/Wiki.png http://static.tournoi-en-ligne.fr/data/themereleases/120120-1440/img/stoneage/game_icon.png 92692e80e27e413417c9e34326c6e0df02a4ba1c 8 5 2012-01-23T08:25:52Z Sourisdudesert 1 wikitext text/x-wiki == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamlist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the bug section in the forum, see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. What is the legal status of this website? All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. I'm a game publisher: why would I like to have my game on Board Game Arena? The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. Meeting players and starting games I launched a new table but nobody is joining? Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. I joined a game. When does the game start? Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game. What is the meaning of the small color circle next to players names? : this player is active. He completed an action very recently. : this player is inactive. He is connected to the website but did not perform any action recently. : this player is offline. During the game What is the meaning of the icons next to players names? : this player must make a move now. : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. A player has to make a move but he/she doesn't. What can I do? First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. Then you can ask this player to confirm that he is still thinking about how to play. If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. What is the current progression of the game I'm playing? A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. What is forbidden on Board Game Arena? Leaving a game in progress on purpose. Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious loosing situation. Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. Running out of time on the game clock. Giving some piece of information about the current game situation that corrupts the normal game flow. Communicating with another player about the game privately (ex: with MSN). Provocation / triumphalism / defeatism ... anything which is not fair play. Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. What is absolutely forbidden in Board Game Arena? Creating multiple account and playing against oneself. Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. What if some player does something wrong? Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had a bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. ab1d2e0d199f098d3288fe43081e422ab59e699c 9 8 2012-01-23T08:28:22Z Sourisdudesert 1 wikitext text/x-wiki == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamlist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game. ===What is the meaning of the small color circle next to players names?=== : this player is active. He completed an action very recently. : this player is inactive. He is connected to the website but did not perform any action recently. : this player is offline. == During the game == ===What is the meaning of the icons next to players names?=== : this player must make a move now. : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious loosing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple account and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had a bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. 556e32db4b9111710ffcbc1ad05f9ec857794e31 10 9 2012-01-23T08:29:03Z Sourisdudesert 1 /* What is the meaning of the small color circle next to players names? */ wikitext text/x-wiki == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamlist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. == During the game == ===What is the meaning of the icons next to players names?=== : this player must make a move now. : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious loosing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple account and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had a bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. c6e6418ab580cd5812c4f613e1be5737fa3a6f7c 11 10 2012-01-23T08:29:43Z Sourisdudesert 1 /* What is the meaning of the icons next to players names? */ wikitext text/x-wiki == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamlist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious loosing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple account and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had a bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. 3678e480ae646ee50cada05e6bf34cac1faf094c 24 11 2012-01-23T08:43:03Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamlist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious loosing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple account and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had a bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. 929b9aebaa71e05b8e961016d35d724169bbcf2d TermsOfService 0 170 1202 2012-01-23T08:20:44Z Sourisdudesert 1 Created page with "tttt" wikitext text/x-wiki tttt 7278934df282ee1027073d9eedbfee4735c627a5 1203 1202 2012-01-23T08:25:52Z Sourisdudesert 1 wikitext text/x-wiki = Board Game Arena Terms of Service = == Welcome to BGA! == Thanks for using our services (“Services”). The Services are provided by Board Game Arena ("BGA"), located at G. Isabelli, 19 bd de la République, 92260 Fontenay-aux-Roses, France. By using our Services, you are agreeing to these terms. Please read them carefully. == Using our Services == You must follow any policies made available to you within the Services. Don’t misuse our Services. For example, don’t interfere with our Services or try to access them using a method other than the interface and the instructions that we provide. You may use our Services only as permitted by law, including applicable export and re-export control laws and regulations. We may suspend or stop providing our Services to you if you do not comply with our terms or policies or if we are investigating suspected misconduct. Using our Services does not give you ownership of any intellectual property rights in our Services or the content you access. You may not use content from our Services unless you obtain permission from its owner or are otherwise permitted by law. These terms do not grant you the right to use any branding or logos used in our Services. Don’t remove, obscure, or alter any legal notices displayed in or along with our Services. Our Services display some content that is not from BGA. This content is the sole responsibility of the entity that makes it available. We may review content to determine whether it is illegal or violates our policies, and we may remove or refuse to display content that we reasonably believe violates our policies or the law. But that does not necessarily mean that we review content, so please don’t assume that we do. In connection with your use of the Services, we may send you service announcements, administrative messages, and other information. You may opt out of some of those communications. == Your BGA Account == You may need a BGA Account in order to use some of our Services. You may create your own BGA Account, or your BGA Account may be assigned to you by an administrator, such as your employer or educational institution. If you are using a BGA Account assigned to you by an administrator, different or additional terms may apply and your administrator may be able to access or disable your account. To protect your BGA Account, keep your password confidential. You are responsible for the activity that happens on or through your BGA Account. Try not to reuse your BGA Account password on third-party applications. If you learn of any unauthorized use of your password or BGA Account, please change it immediately from your preferences. == Your responsibility as a BGA player ("the Player") == 1) The Player is solely responsible for any messages, content and information posted by him on the site since, in its capacity as host of the service considered here, under the provisions of Law No. 2004 -575 of 21 June 2004 on confidence in the digital economy, BGA can not be responsible for the content posted or transmitted by Players on the Site and on which BGA exercises no control and monitoring. The Player expressly agrees, under penalty of criminal responsibility or civil liability, that it broadcasts messages are not likely to, without this list is exhaustive, including: - violate intellectual property rights of third parties: in this respect the Player undertakes not to reproduce or communicate publicly on the Site or the material protected under copyright, trademark filed as or more generally protected by other intellectual property rights held by third parties without the prior consent of the holders of such proprietary rights. - Contain computer viruses likely to interrupt, destroy or impair the functionality of the Site; - Being an apologist for crimes or contain illegal messages, threatening, or pedophile nature, pornographic, defamatory, obscene, hateful, racist, antisemitic, xenophobic, revisionist or contrary to public order or morality; - Infringe privacy or dignity of others; - Incite violence, fanaticism, crime, suicide, hatred due to religion, race, gender, sexual orientation, ethnicity, - Harass other players with whom the Player would be contacted when discussing the different communication areas of the site; - Promote or encourage any criminal activity or enterprise; - Solicit and / or disclose passwords and / or personal information for commercial or unlawful purposes; - Transmit any chain e-mails, unsolicited mass mailings, instant messages, commercials or unwanted unsolicited mail; - Contain advertisements and / or solicitations to offer products and / or commercial services through the Site. - Contain addresses or hypertext links to external sites whose content is contrary to the laws and regulations, which violate the rights of others or is contrary to these terms. 2) The Player agrees to hold only one account on BGA, unless otherwise approved by BGA. We reserve the right to terminate any multiple accounts attributable to the same person. 3) The Player agrees not to resort to the use of automated systems such as scripts to play or send messages. 4) The Player is solely responsible for keeping and confidentiality of their password and agrees not to communicate at any time whatsoever, his password to any other player or to use the account, the username and password of another Player. It also undertakes not to create multiple accounts. The Player guarantees the accuracy of information provided to BGA for purposes of registration and agrees to notify any subsequent changes. 5) The Player acknowledges that BGA reserves, in case his use of the site would be contrary to these Terms and generally applicable laws and regulatory provisions in force, to immediately and without notice of its deregistration Site services and / or blocking its access to the Site. 6) BGA reserves, assuming the Player would be responsible for an offense under the legislation or affect the rights of third parties the right to provide, upon request of all legitimate authority (courts, administrative authorities, police), all information allowing or facilitating the identification of the offending Player. 7) The Player is required to notify BGA, using the "Report this player" function, any misuse of the Site which he has knowledge, including any message whose contents violate the above prohibitions set or more generally applicable laws and regulatory provisions in force. == Privacy and Copyright Protection == BGA's [http://boardgamearena.com/#!doc/privacy privacy policies] explain how we treat your personal data and protect your privacy when you use our Services. By using our Services, you agree that BGA can use such data in accordance with our privacy policies. We respond to notices of alleged copyright infringement and terminate accounts of repeat infringers according to the process set out in France and the European Union. If you think somebody is violating your copyrights and want to notify us, you can contact us directly though our "Contact" section. BGA wishes to place a cookie on the computer of the subscriber. A cookie can not be personally identified. However, it records information relating to the navigation of the computer on the Site (pages viewed, date and time of visit, etc.). BGA that can read during subsequent visits. This will allow for easier navigation and avoid having to provide each new visit the information already sent an earlier date. It is stated that the shelf life of "cookies" BGA implanted is less than 6 (six) months. BGA notify the Player that the setting of their browser to alert you of the presence of "cookies" and that he may oppose the registration of "cookies". == Your Content in our Services == Some of our Services allow you to upload, submit, store, send or receive content. You retain ownership of any intellectual property rights that you hold in that content. In short, what belongs to you stays yours. When you upload, submit, store, send or receive content to or through our Services, you give BGA (and those we work with) a worldwide license to use, host, store, reproduce, modify, create derivative works (such as those resulting from translations, adaptations or other changes we make so that your content works better with our Services), communicate, publish, publicly perform, publicly display and distribute such content. The rights you grant in this license are for the limited purpose of operating, promoting, and improving our Services, and to develop new ones. This license continues even if you stop using our Services. Some Services may offer you ways to access and remove content that has been provided to that Service. Also, in some of our Services, there are terms or settings that narrow the scope of our use of the content submitted in those Services. Make sure you have the necessary rights to grant us this license for any content that you submit to our Services. Our automated systems analyze your content to provide you personally relevant features. This analysis occurs as the content is sent, received, and when it is stored. You can find more information about how BGA uses and stores content in the privacy policy or additional terms for particular Services. If you submit feedback or suggestions about our Services, we may use your feedback or suggestions without obligation to you. == About Software in our Services == When a Service requires or includes downloadable software, this software may update automatically on your device once a new version or feature is available. Some Services may let you adjust your automatic update settings. BGA gives you a personal, worldwide, royalty-free, non-assignable and non-exclusive license to use the software provided to you by Google as part of the Services. This license is for the sole purpose of enabling you to use and enjoy the benefit of the Services as provided by BGA, in the manner permitted by these terms. You may not copy, modify, distribute, sell, or lease any part of our Services or included software, nor may you reverse engineer or attempt to extract the source code of that software, unless laws prohibit those restrictions or you have our written permission. Open source software is important to us. Some software used in our Services may be offered under an open source license that we will make available to you. There may be provisions in the open source license that expressly override some of these terms. == Modifying and Terminating our Services == We are constantly changing and improving our Services. We may add or remove functionalities or features, and we may suspend or stop a Service altogether. You can stop using our Services at any time, although we’ll be sorry to see you go. BGA may also stop providing Services to you, or add or create new limits to our Services at any time. We believe that you own your data and preserving your access to such data is important. If we discontinue a Service, where reasonably possible, we will give you reasonable advance notice and a chance to get information out of that Service. == Our Warranties and Disclaimers == We provide our Services using a commercially reasonable level of skill and care and we hope that you will enjoy using them. But there are certain things that we don’t promise about our Services. OTHER THAN AS EXPRESSLY SET OUT IN THESE TERMS OR ADDITIONAL TERMS, NEITHER BGA NOR ITS SUPPLIERS OR DISTRIBUTORS MAKE ANY SPECIFIC PROMISES ABOUT THE SERVICES. FOR EXAMPLE, WE DON’T MAKE ANY COMMITMENTS ABOUT THE CONTENT WITHIN THE SERVICES, THE SPECIFIC FUNCTIONS OF THE SERVICES, OR THEIR RELIABILITY, AVAILABILITY, OR ABILITY TO MEET YOUR NEEDS. WE PROVIDE THE SERVICES “AS IS”. SOME JURISDICTIONS PROVIDE FOR CERTAIN WARRANTIES, LIKE THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. TO THE EXTENT PERMITTED BY LAW, WE EXCLUDE ALL WARRANTIES. == Liability for our Services == WHEN PERMITTED BY LAW, BGA WILL NOT BE RESPONSIBLE FOR LOST PROFITS, REVENUES, OR DATA, FINANCIAL LOSSES OR INDIRECT, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES. TO THE EXTENT PERMITTED BY LAW, THE TOTAL LIABILITY OF BGA, AND ITS SUPPLIERS AND DISTRIBUTORS, FOR ANY CLAIMS UNDER THESE TERMS, INCLUDING FOR ANY IMPLIED WARRANTIES, IS LIMITED TO THE AMOUNT YOU PAID US TO USE THE SERVICES (OR, IF WE CHOOSE, TO SUPPLYING YOU THE SERVICES AGAIN). IN ALL CASES, BGA, AND ITS SUPPLIERS AND DISTRIBUTORS, WILL NOT BE LIABLE FOR ANY LOSS OR DAMAGE THAT IS NOT REASONABLY FORESEEABLE. == Business uses of our Services == If you are using our Services on behalf of a business, that business accepts these terms. It will hold harmless and indemnify BGA and its affiliates, officers, agents, and employees from any claim, suit or action arising from or related to the use of the Services or violation of these terms, including any liability or expense arising from claims, losses, damages, suits, judgments, litigation costs and attorneys’ fees. == About these Terms == We may modify these terms or any additional terms that apply to a Service to, for example, reflect changes to the law or changes to our Services. You should look at the terms regularly. Changes will be effective immediately. If you do not agree to the modified terms for a Service, you should discontinue your use of that Service. If there is a conflict between these terms and the additional terms, the additional terms will control for that conflict. These terms control the relationship between BGA and you. They do not create any third party beneficiary rights. If you do not comply with these terms, and we don’t take action right away, this doesn’t mean that we are giving up any rights that we may have (such as taking action in the future). If it turns out that a particular term is not enforceable, this will not affect any other terms. The laws of France will apply to any disputes arising out of or relating to these terms or the Services. All claims arising out of or relating to these terms or the Services will be litigated exclusively in the French courts. For information about how to contact BGA, please visit our [http://boardgamearena.com/#!doc/contact contact page]. d93aa312133a6c52fec21a3a537193b7e17377b8 Help 0 4 7 2012-01-23T08:23:35Z Sourisdudesert 1 Created page with "An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com]] Forums are also helpful to get information. == Hel..." wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com]] Forums are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena]] ** [[About us]] ** [[Club Board Game Arena]] ** [[Contact us]] === Detailled help === * [[Getting started]] * [[Referral]] * [[Browser support]] * [[Moderation and grades]] * [[Game clock]] * [[Rating]] * [[Reputation]] * [[Translation guidelines]] bb066b4658e936f326aa0ee996bb45e23cb8c2b0 12 7 2012-01-23T08:30:09Z Sourisdudesert 1 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com] Forums are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena]] ** [[About us]] ** [[Club Board Game Arena]] ** [[Contact us]] === Detailled help === * [[Getting started]] * [[Referral]] * [[Browser support]] * [[Moderation and grades]] * [[Game clock]] * [[Rating]] * [[Reputation]] * [[Translation guidelines]] 95118ab41bd97e3433383cecebb8e7e133c40b10 13 12 2012-01-23T08:30:21Z Sourisdudesert 1 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena]] ** [[About us]] ** [[Club Board Game Arena]] ** [[Contact us]] === Detailled help === * [[Getting started]] * [[Referral]] * [[Browser support]] * [[Moderation and grades]] * [[Game clock]] * [[Rating]] * [[Reputation]] * [[Translation guidelines]] 16b14d9549ac5aa2e310653b33e55be4abd27bb0 About Board Game Arena 0 5 14 2012-01-23T08:31:22Z Sourisdudesert 1 Created page with "With '''Board Game Arena''' you can play board games online with the whole world. Board Game Arena is a next generation game platform which makes online gaming more simple a..." wikitext text/x-wiki With '''Board Game Arena''' you can play board games online with the whole world. Board Game Arena is a next generation game platform which makes online gaming more simple and attractive: * Nothing to install: play straight from your browser, from anywhere, at anytime. * Real time: your opponents are online, you play "live". * Simple: if you know the game, then you know how to play online. * Free. Board Game Arena offers a [http://en.boardgamearena.com/#!gamelist growing selection of board and card games]. We are specialized in modern adults games ("European style games"). This game platform has been designed to host any kind of game. This flexibility allow us to propose a '''new game every month'''. b9d59b3d8e80f8df79151e82dbdede2ee6efc91c 25 14 2012-01-23T08:43:15Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] With '''Board Game Arena''' you can play board games online with the whole world. Board Game Arena is a next generation game platform which makes online gaming more simple and attractive: * Nothing to install: play straight from your browser, from anywhere, at anytime. * Real time: your opponents are online, you play "live". * Simple: if you know the game, then you know how to play online. * Free. Board Game Arena offers a [http://en.boardgamearena.com/#!gamelist growing selection of board and card games]. We are specialized in modern adults games ("European style games"). This game platform has been designed to host any kind of game. This flexibility allow us to propose a '''new game every month'''. 4f7854886444585b16fecb70e4b46c419e6db368 28 25 2012-01-23T08:43:48Z Sourisdudesert 1 wikitext text/x-wiki With '''Board Game Arena''' you can play board games online with the whole world. Board Game Arena is a next generation game platform which makes online gaming more simple and attractive: * Nothing to install: play straight from your browser, from anywhere, at anytime. * Real time: your opponents are online, you play "live". * Simple: if you know the game, then you know how to play online. * Free. Board Game Arena offers a [http://en.boardgamearena.com/#!gamelist growing selection of board and card games]. We are specialized in modern adults games ("European style games"). This game platform has been designed to host any kind of game. This flexibility allow us to propose a '''new game every month'''. b9d59b3d8e80f8df79151e82dbdede2ee6efc91c About us 0 6 15 2012-01-23T08:31:55Z Sourisdudesert 1 Created page with "First, we should say that we are gamers. Real, complete boardgames addicts. We designed '''Board Game Arena''' for players who can't play for real because of time, geographic..." wikitext text/x-wiki First, we should say that we are gamers. Real, complete boardgames addicts. We designed '''Board Game Arena''' for players who can't play for real because of time, geographic or social constraints. We would like to provide a new game experience with the best of two worlds: video games and board games. Although we aim to provide high quality online games, we are still convinced that the best way to enjoy board games is around a *real* table with friends. This is one of the reason we strongly recommand you to buy physical copies of the games you discover on BGA. The other reason is simple to understand: each game sale is also a revenue for an author and an editor (... we've come full circle). [[Contact us]] 09d076571c067045048850f642e222a1e1485eb7 26 15 2012-01-23T08:43:26Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] First, we should say that we are gamers. Real, complete boardgames addicts. We designed '''Board Game Arena''' for players who can't play for real because of time, geographic or social constraints. We would like to provide a new game experience with the best of two worlds: video games and board games. Although we aim to provide high quality online games, we are still convinced that the best way to enjoy board games is around a *real* table with friends. This is one of the reason we strongly recommand you to buy physical copies of the games you discover on BGA. The other reason is simple to understand: each game sale is also a revenue for an author and an editor (... we've come full circle). [[Contact us]] 366663e98e2fe4f1c5659450c36d0b7db247b03f 27 26 2012-01-23T08:43:39Z Sourisdudesert 1 wikitext text/x-wiki First, we should say that we are gamers. Real, complete boardgames addicts. We designed '''Board Game Arena''' for players who can't play for real because of time, geographic or social constraints. We would like to provide a new game experience with the best of two worlds: video games and board games. Although we aim to provide high quality online games, we are still convinced that the best way to enjoy board games is around a *real* table with friends. This is one of the reason we strongly recommand you to buy physical copies of the games you discover on BGA. The other reason is simple to understand: each game sale is also a revenue for an author and an editor (... we've come full circle). [[Contact us]] 09d076571c067045048850f642e222a1e1485eb7 Club 0 7 16 2012-01-23T08:32:39Z Sourisdudesert 1 Redirected page to [[Club Board Game Arena]] wikitext text/x-wiki #REDIRECT [[Club Board Game Arena]] fac244084d01208926b41fc59a051c6ed0c0748a Club Board Game Arena 0 8 17 2012-01-23T08:34:49Z Sourisdudesert 1 Created page with "Board Game Arena's main goal is to promote board games to a large audience. This is the reason why the service is '''free''' for everyone, and '''meant to stay that way'''. A..." wikitext text/x-wiki Board Game Arena's main goal is to promote board games to a large audience. This is the reason why the service is '''free''' for everyone, and '''meant to stay that way'''. As you can imagine, though, this website needs a lot of time and some money to keep things running smoothly. Some players are helping us with contributions or through donations. This website can exist only because of the help from these players, and to thank them we make them members of the "Board Game Arena Club". == How can I become a club member ? == The three main ways to become a club member are: * Make this website known (see referral) * [http://en.boardgamearena.com/#!translationhq Contribute to translate] this website * Support this website with a donation (payment buttons below) {| |Donate '''20€''' (1 year club membership) |Donate '''11€''' (6 months club membership) |Donate '''4€''' (2 months club membership) |- |{one_year_membership} |{six_month_membership} |{two_month_membership} |} ==Why should I join the club ?== The main reason you should join the club is to support this website. Also, as a token of appreciation for their support, we give to club members an access to some statistics: ELO ranking of all members including yours (instead of ), games statistics and specific player statistics for each game. Why can't you just have a standard donation system where I can choose any money amount ? With this "club" system, we try to highlight players who supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time. Many websites are using a more classical approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena chooses to set 3 fixed amounts for donations in order to rely on a bigger number of small donors. Is it mandatory to join the club ? Of course not. You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra : you don't need statistics to play and have fun, don't you ? As a matter of fact, most players are not club members. What is a beginner account ? When you join Board Game Arena, your get a "beginner account" () for 30 days. This beginner account allow you to view your own ELO ranking () for each game. After 30 days, your account becomes a standard non member account (). What becomes of the money ? Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost). Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)... A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone ! 05a49a509de676c255b30cd47a1719a179d3873e 18 17 2012-01-23T08:35:14Z Sourisdudesert 1 /* How can I become a club member ? */ wikitext text/x-wiki Board Game Arena's main goal is to promote board games to a large audience. This is the reason why the service is '''free''' for everyone, and '''meant to stay that way'''. As you can imagine, though, this website needs a lot of time and some money to keep things running smoothly. Some players are helping us with contributions or through donations. This website can exist only because of the help from these players, and to thank them we make them members of the "Board Game Arena Club". == How can I become a club member ? == The three main ways to become a club member are: * Make this website known (see [[referral]]) * [http://en.boardgamearena.com/#!translationhq Contribute to translate] this website * Support this website with a donation (payment buttons below) {| |Donate '''20€''' (1 year club membership) |Donate '''11€''' (6 months club membership) |Donate '''4€''' (2 months club membership) |- |{one_year_membership} |{six_month_membership} |{two_month_membership} |} ==Why should I join the club ?== The main reason you should join the club is to support this website. Also, as a token of appreciation for their support, we give to club members an access to some statistics: ELO ranking of all members including yours (instead of ), games statistics and specific player statistics for each game. Why can't you just have a standard donation system where I can choose any money amount ? With this "club" system, we try to highlight players who supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time. Many websites are using a more classical approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena chooses to set 3 fixed amounts for donations in order to rely on a bigger number of small donors. Is it mandatory to join the club ? Of course not. You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra : you don't need statistics to play and have fun, don't you ? As a matter of fact, most players are not club members. What is a beginner account ? When you join Board Game Arena, your get a "beginner account" () for 30 days. This beginner account allow you to view your own ELO ranking () for each game. After 30 days, your account becomes a standard non member account (). What becomes of the money ? Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost). Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)... A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone ! eb70d022960d5fd26851ae3c461dcf0de7f275f4 19 18 2012-01-23T08:37:03Z Sourisdudesert 1 wikitext text/x-wiki Board Game Arena's main goal is to promote board games to a large audience. This is the reason why the service is '''free''' for everyone, and '''meant to stay that way'''. As you can imagine, though, this website needs a lot of time and some money to keep things running smoothly. Some players are helping us with contributions or through donations. This website can exist only because of the help from these players, and to thank them we make them members of the "Board Game Arena Club". == How can I become a club member ? == The three main ways to become a club member are: * Make this website known (see [[referral]]) * [http://en.boardgamearena.com/#!translationhq Contribute to translate] this website * Support this website with a donation (payment buttons below) {| |Donate '''20€''' (1 year club membership) |Donate '''11€''' (6 months club membership) |Donate '''4€''' (2 months club membership) |- |{one_year_membership} |{six_month_membership} |{two_month_membership} |} ==Why should I join the club ?== The main reason you should join the club is to support this website. Also, as a token of appreciation for their support, we give to club members an access to some statistics: ELO ranking http://en.boardgamearena.com/theme/img/common/rank.png of all members including yours (instead of http://fr.boardgamearena.com/theme/img/common/rankmask.png), games statistics and specific player statistics for each game. ==Why can't you just have a standard donation system where I can choose any money amount ?== With this "club" system, we try to highlight players who supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time. Many websites are using a more classical approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena chooses to set 3 fixed amounts for donations in order to rely on a bigger number of small donors. ==Is it mandatory to join the club ?== Of course not. You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra : you don't need statistics to play and have fun, don't you ? As a matter of fact, most players are not club members. ==What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif == When you join Board Game Arena, your get a "beginner account" (http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif) for 30 days. This beginner account allow you to view your own ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) for each game. After 30 days, your account becomes a standard '''non member''' account (http://en.boardgamearena.com/theme/img/accounttypes/free.gif). ==What becomes of the money ?== Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost). Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)... A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone ! a12f51dc80f363786676e4551d1473aabc326650 20 19 2012-01-23T08:38:47Z Sourisdudesert 1 /* Why should I join the club ? */ wikitext text/x-wiki Board Game Arena's main goal is to promote board games to a large audience. This is the reason why the service is '''free''' for everyone, and '''meant to stay that way'''. As you can imagine, though, this website needs a lot of time and some money to keep things running smoothly. Some players are helping us with contributions or through donations. This website can exist only because of the help from these players, and to thank them we make them members of the "Board Game Arena Club". == How can I become a club member ? == The three main ways to become a club member are: * Make this website known (see [[referral]]) * [http://en.boardgamearena.com/#!translationhq Contribute to translate] this website * Support this website with a donation (payment buttons below) {| |Donate '''20€''' (1 year club membership) |Donate '''11€''' (6 months club membership) |Donate '''4€''' (2 months club membership) |- |{one_year_membership} |{six_month_membership} |{two_month_membership} |} ==Why should I join the club ?== The main reason you should join the club is to support this website. Also, as a token of appreciation for their support, we give to club members an access to some statistics: ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) of all members including yours (instead of http://fr.boardgamearena.com/theme/img/common/rankmask.png), games statistics and specific player statistics for each game. ==Why can't you just have a standard donation system where I can choose any money amount ?== With this "club" system, we try to highlight players who supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time. Many websites are using a more classical approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena chooses to set 3 fixed amounts for donations in order to rely on a bigger number of small donors. ==Is it mandatory to join the club ?== Of course not. You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra : you don't need statistics to play and have fun, don't you ? As a matter of fact, most players are not club members. ==What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif == When you join Board Game Arena, your get a "beginner account" (http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif) for 30 days. This beginner account allow you to view your own ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) for each game. After 30 days, your account becomes a standard '''non member''' account (http://en.boardgamearena.com/theme/img/accounttypes/free.gif). ==What becomes of the money ?== Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost). Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)... A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone ! 07d7d56ac7137270da1cb1e701810fd74c30b286 Contact us 0 9 21 2012-01-23T08:40:19Z Sourisdudesert 1 Created page with "'''Board Game Arena''' is located in France. == E-mail contact == contact(at)boardgamearena.com We receive *a lot* of e-mails. Please do not send us an e-mail if: * ... i..." wikitext text/x-wiki '''Board Game Arena''' is located in France. == E-mail contact == contact(at)boardgamearena.com We receive *a lot* of e-mails. Please do not send us an e-mail if: * ... if you want to report a bug, please do it in the corresponding forum. * ... if you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile == Responsible == G. Isabelli 19 bd république 92 260 Fontenay-aux-Roses FRANCE +33 6 17 25 80 34 3fa5849702cf1b1b19bd3acb243c32dbb041a4a9 Getting started 0 10 22 2012-01-23T08:42:02Z Sourisdudesert 1 Created page with "With '''Board Game Arena''' you can play within a few clicks. By choosing "[http://en.boardgamearena.com/#!lobby Play now]" on the left menu, you get a list of game tables wa..." wikitext text/x-wiki With '''Board Game Arena''' you can play within a few clicks. By choosing "[http://en.boardgamearena.com/#!lobby Play now]" on the left menu, you get a list of game tables waiting for players. You can join a game by clicking on "View table" then "Join game". If you prefer, you can create a new game table: click on the "Launch table" button that corresponds to the game you want to play, and wait for your opponents. Important to know before you start: * It's much better to join a table already created than to create a new one. * For most popular games you will find opponents at any time. For the others, try to connect around peak hour (around 22h CEST) to maximize your chances. * When you start a game you can't leave the table until it ends. If you leave you will receive a penalty which cause you difficulties to find opponents later. 00acad1f28c408117fc7c59eac2c4627a71d7e72 23 22 2012-01-23T08:42:52Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] With '''Board Game Arena''' you can play within a few clicks. By choosing "[http://en.boardgamearena.com/#!lobby Play now]" on the left menu, you get a list of game tables waiting for players. You can join a game by clicking on "View table" then "Join game". If you prefer, you can create a new game table: click on the "Launch table" button that corresponds to the game you want to play, and wait for your opponents. Important to know before you start: * It's much better to join a table already created than to create a new one. * For most popular games you will find opponents at any time. For the others, try to connect around peak hour (around 22h CEST) to maximize your chances. * When you start a game you can't leave the table until it ends. If you leave you will receive a penalty which cause you difficulties to find opponents later. 860720b52040414f964590d5eb8639fb21735545 Referral 0 11 29 2012-01-23T08:46:41Z Sourisdudesert 1 Created page with "[[Category:Help]] When new players discover Board Game Arena thanks to you, you become a member of [[Club Board Game Arena]] == How does this work? == Each time a new player..." wikitext text/x-wiki [[Category:Help]] When new players discover Board Game Arena thanks to you, you become a member of [[Club Board Game Arena]] == How does this work? == Each time a new player create an account on Board Game Arena from you referrer web address (see below), he becomes one of your '''referees'''. As soon as this referee played few games, you become a member of BGA club. == How to get referees? == To recruit referees, use your personal referrer web address: {sponsorshipurl} New players MUST create an account from this web address to become one of your referees. == How to get many referees? == * [http://boardgamearena.com/#!doc/sponsor?facebook Tell my friends on Facebook] * [http://boardgamearena.com/#!doc/sponsor?twitter Tell my followers on Twitter] * [http://boardgamearena.com/#!doc/sponsor?email Tell my friends by email] * Publish my personal web address in some forum, send it by MSN, ... == How many BGA club membership days can I win? == As soon as your first referee finish his '''third''' game on Board Game Arena, you win a '''1 month''' BGA club membership. ''Note: your account upgrade will be effective within 24 hours.'' As soon as you get '''2 referees''' with at least '''4 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership. As soon as you get '''3 referees''' with at least '''5 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership. ... and so on: as your referees number grows you can win many free memberships ! == Referees and multiple account == It is of course forbidden to create fake referee accounts to win free memberships. 52e8ab57da4a8638af8bcfdb8ab9549d2bd5ad12 Rummad:Help 14 12 30 2012-01-23T08:47:01Z Sourisdudesert 1 Created page with "Board Game Arena help pages" wikitext text/x-wiki Board Game Arena help pages adc7e25dcb01838e74ee4f7611812cf2762d2767 Browser support 0 13 31 2012-01-23T08:47:52Z Sourisdudesert 1 Created page with "Board Game Arena is using the most recent web technology to make it possible for you to play without installing anything on your computer: no software to download, no plugin t..." wikitext text/x-wiki Board Game Arena is using the most recent web technology to make it possible for you to play without installing anything on your computer: no software to download, no plugin to install, ... Consequently, to play you need to use a recent web browser. Generally speaking, the more recent your web browser is, the more pleasant your game experience on Board Game Arena will be. We officially support the following browsers: * Mozilla Firefox 3.5+ * Google Chrome 4+ * Internet Explorer 8 (partial support for IE7) * Internet Explorer 9 * Safari 4+ (Note: we are NOT supporting iPad or similar tablets) This website uses Javascript technology and your browser's graphics possibilities intensely. Thus, if you want to have the best game experience with Board Game Arena, you should use one of these browsers: * Mozilla Firefox 4 * Google Chrome 10 32bb40e75bb29f6d724daafd30c7906adcadadb7 36 31 2012-01-23T08:52:07Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] Board Game Arena is using the most recent web technology to make it possible for you to play without installing anything on your computer: no software to download, no plugin to install, ... Consequently, to play you need to use a recent web browser. Generally speaking, the more recent your web browser is, the more pleasant your game experience on Board Game Arena will be. We officially support the following browsers: * Mozilla Firefox 3.5+ * Google Chrome 4+ * Internet Explorer 8 (partial support for IE7) * Internet Explorer 9 * Safari 4+ (Note: we are NOT supporting iPad or similar tablets) This website uses Javascript technology and your browser's graphics possibilities intensely. Thus, if you want to have the best game experience with Board Game Arena, you should use one of these browsers: * Mozilla Firefox 4 * Google Chrome 10 03a7ec9371d3e330c0ce5224bdda0f3bf49ec060 Moderation and grades 0 14 32 2012-01-23T08:49:30Z Sourisdudesert 1 Created page with "Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit o..." wikitext text/x-wiki Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a '''mortal'''. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the '''angel''' grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to '''devilkin''' or '''demon'''. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. == All grades == * '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraph can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherub check that Seraph are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...) * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. 05df6f50ad4723b2aa3c8dfd1e36e49da6dcb38e 35 32 2012-01-23T08:51:55Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a '''mortal'''. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the '''angel''' grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to '''devilkin''' or '''demon'''. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. == All grades == * '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraph can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherub check that Seraph are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...) * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. 49931146459d3900e8e8099ce554da943f7a304b Game clock 0 15 33 2012-01-23T08:51:23Z Sourisdudesert 1 Created page with "On '''Board Game Arena''' you are playing "live" (real time). Then you has a delay to play your moves. Your initial delay at the beginning of a game is most of the time '''3 ..." wikitext text/x-wiki On '''Board Game Arena''' you are playing "live" (real time). Then you has a delay to play your moves. Your initial delay at the beginning of a game is most of the time '''3 minutes'''. At each turn, or on specific occasion, you get an additional delay. If you have no more time to play, you will get a penalty and can become eligible to be expelled from the game. == Time to think == Your alloted time to think is displayed on the right of your player's name. When it's your turn to player, this time is also displayed at the top of the web page. == Game speed == Table administrator can make a choice between 4 game speed profile: * Fast * Normal * Slow * Without time limit The additional amount of time credited each turn depends on chosen game speed profile. Be careful to check game speed before game start to adapt your timing. Note: playing without time limit is strongly discouraged, except if you are playing with friends or to discover a new game. Remember that without time limit, you can't expel a player that stops playing. == Running out of time == As soon as you run out of time, you get a clock penalty. If you goes over your alloted time by more than 3/4/5 minutes (depending on game speed), any opponent can expel you from the game. Of course, it is strongly advised not to run out of time ... == Move time limit == In addition to your classical time to think, you have a limited time alloted for each move. When it's your turn to play, a red bar appears on top of the web page. It symbolized the remaining time limit for this move. The amount of time depends on game speed. If you goes over this limit, you become eligible to be expelled from the game. == "My opponent is too slow" == Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his alloted time to think. If you want to play fast, set up or join table with "fast" mode only, but don't force an opponent to play when he has the right to do so. == "I would like to think a little" == If you are in a critical step of the game and want to take some time to think, you can click on the link "I would like to think a little" on the top right of the page. Thus, your opponents will receive a message and won't be thinking you are away from keyboard. Clicking on this link is not mandatory, but we encourage its use for courtesy. 1cfe01c7a6e760c91b41e2d84865f9706010ebdf 34 33 2012-01-23T08:51:44Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] On '''Board Game Arena''' you are playing "live" (real time). Then you has a delay to play your moves. Your initial delay at the beginning of a game is most of the time '''3 minutes'''. At each turn, or on specific occasion, you get an additional delay. If you have no more time to play, you will get a penalty and can become eligible to be expelled from the game. == Time to think == Your alloted time to think is displayed on the right of your player's name. When it's your turn to player, this time is also displayed at the top of the web page. == Game speed == Table administrator can make a choice between 4 game speed profile: * Fast * Normal * Slow * Without time limit The additional amount of time credited each turn depends on chosen game speed profile. Be careful to check game speed before game start to adapt your timing. Note: playing without time limit is strongly discouraged, except if you are playing with friends or to discover a new game. Remember that without time limit, you can't expel a player that stops playing. == Running out of time == As soon as you run out of time, you get a clock penalty. If you goes over your alloted time by more than 3/4/5 minutes (depending on game speed), any opponent can expel you from the game. Of course, it is strongly advised not to run out of time ... == Move time limit == In addition to your classical time to think, you have a limited time alloted for each move. When it's your turn to play, a red bar appears on top of the web page. It symbolized the remaining time limit for this move. The amount of time depends on game speed. If you goes over this limit, you become eligible to be expelled from the game. == "My opponent is too slow" == Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his alloted time to think. If you want to play fast, set up or join table with "fast" mode only, but don't force an opponent to play when he has the right to do so. == "I would like to think a little" == If you are in a critical step of the game and want to take some time to think, you can click on the link "I would like to think a little" on the top right of the page. Thus, your opponents will receive a message and won't be thinking you are away from keyboard. Clicking on this link is not mandatory, but we encourage its use for courtesy. 82143c3b2c0b2426ec6fbc8637e3c739608e6bfb Rating 0 16 37 2012-01-23T08:53:27Z Sourisdudesert 1 Created page with " == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign . Example: 1648 http://fr.boardgamearena.com/theme..." wikitext text/x-wiki == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign . Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you loose a game. == How is my ELO ranking computed ? == The BGA ELO system is inspired by the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. Let's try to make it simple: the points you win/loose after each game depends on the ranking of your opponents. If you win at a table with opponents stronger than you, your ranking will increase a lot. If you loose at the same table, your ranking will decrease a little. And so on ... In case there are more than 2 players at the table, we take into account the final rank. This is the reason it is important to continue fighting for the second place during the game if you think you can't win. == Okay, but I want to know the formula ! == At first, when someone left a game for any reason this game is not taken into account by the ELO rating system. * Table Level (TL) is the average of ELO ratings of all players at this table. * The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player). * The performance (P) of a player is TL+S. * The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO 6a46415cd42c733e8f6c21168baf058ec0295e5d 38 37 2012-01-23T08:54:06Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you loose a game. == How is my ELO ranking computed ? == The BGA ELO system is inspired by the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. Let's try to make it simple: the points you win/loose after each game depends on the ranking of your opponents. If you win at a table with opponents stronger than you, your ranking will increase a lot. If you loose at the same table, your ranking will decrease a little. And so on ... In case there are more than 2 players at the table, we take into account the final rank. This is the reason it is important to continue fighting for the second place during the game if you think you can't win. == Okay, but I want to know the formula ! == At first, when someone left a game for any reason this game is not taken into account by the ELO rating system. * Table Level (TL) is the average of ELO ratings of all players at this table. * The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player). * The performance (P) of a player is TL+S. * The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO 9b83bb61530a3473b4ced7a0e88dac9b3121235a Reputation 0 17 39 2012-01-23T08:57:12Z Sourisdudesert 1 Created page with "[[Category:Help]] == What is reputation ? == On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance. To a..." wikitext text/x-wiki [[Category:Help]] == What is reputation ? == On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance. To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items: * Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png) * % of games you finished * % of games you finished with no clock penalties Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits. == How to increase my reputation / what makes my reputation decrease ? == At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks. * a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player. * a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player. You can only give a single thumb (green or red) to a single player. If your opinion evolved you can click again on a thumb to reflect this change. As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended to leave the game or to expel this player. By nature, opinions are subjectives. There is nothing we can do for you if you receive a for an unfair reason. However, we know by experience that this system has a lot of advantages and give a relevant information. == Advices: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png == * Be polite ! Say at least "hello" and "good luck" at the beginning of the game. "good game" ("gg") at the end of the game. * When you need some time to think, click on "I would like to think a little" link. * Stay calm in any circumstances: it's a game. * Don't press your opponent to play if he has some time left. * If you really can't finish the game (this is not supposed to happened...), then say you are sorry and leave the game by your own to save your opponents time. * Be a good looser: if your loose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a for this reason!). * Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation. == What are the consequences of a bad reputation ? == A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you. It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents. ccf3fbc039164bc5b2119e80643b725a1e974e87 40 39 2012-01-23T08:57:39Z Sourisdudesert 1 /* Advices: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png */ wikitext text/x-wiki [[Category:Help]] == What is reputation ? == On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance. To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items: * Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png) * % of games you finished * % of games you finished with no clock penalties Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits. == How to increase my reputation / what makes my reputation decrease ? == At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks. * a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player. * a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player. You can only give a single thumb (green or red) to a single player. If your opinion evolved you can click again on a thumb to reflect this change. As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended to leave the game or to expel this player. By nature, opinions are subjectives. There is nothing we can do for you if you receive a for an unfair reason. However, we know by experience that this system has a lot of advantages and give a relevant information. == Advices: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png == * Be polite ! Say at least "hello" and "good luck" at the beginning of the game. "good game" ("gg") at the end of the game. * When you need some time to think, click on "I would like to think a little" link. * Stay calm in any circumstances: it's a game. * Don't press your opponent to play if he has some time left. * If you really can't finish the game (this is not supposed to happened...), then say you are sorry and leave the game by your own to save your opponents time. * Be a good looser: if your loose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!). * Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation. == What are the consequences of a bad reputation ? == A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you. It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents. 170ac86366603b161f7deb20712a920f5e460408 Translation guidelines 0 18 41 2012-01-23T08:58:49Z Sourisdudesert 1 Created page with "The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena in any language, in order to ena..." wikitext text/x-wiki The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena in any language, in order to enable more people to discover and play boardgames, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10 years old nephew and he doesn't speak english yet, no problem! Just help us translate Board Game Arena into your language! == What can be translated ? == Every string of text for the mainsite interface and for the games interfaces is 'internationalized' and can be translated. For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometimes later... == Who should translate ? == This is important : only native speakers of a given language should translate in this language. When translating a game, the translator should know the game and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronomical rules usual for the gaming audience of their country. As Board Game Arena's team's mothertongue is french, we will take charge of the french translations. We will also release the first version of the english translation. As we are not perfect speakers of Shakespeare's language, these translation will be open for review and correction from native english speakers under the same conditions as the other languages. == About context == Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot uncorrect forms (if any) while playing and be able to correct them. Also, you can ask us for context in the translation forum (in english or in french), and we will try to look it up and provide the information. == When will the site be made available in a new language it is being translated into ? == As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in this language. == I fixed some translations, but they don't appear to have changed on the site ? == Translation files are updated each time we do a new release, so you have to wait until the next BGA release for your changes to appear on the site. Usually this should happen every week or two. == How long will it be possible to change the translations ? == The first translations may not be perfect (as explained in the 'about context' section). So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore. == Is there some reward for translating ? == Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated). This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward among all! == Translation tips == Use the 'TAB' key to go from one text box to another. This is easier than clicking. Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}). When in doubt, leave a comment for the next translator. When you fix someone's translation, leave a comment if the reason for the change is not obvious. When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing. f785003cc6caeb1c2fd8407b5ea381eb725dad8b 42 41 2012-01-23T08:59:19Z Sourisdudesert 1 /* About context */ wikitext text/x-wiki The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena in any language, in order to enable more people to discover and play boardgames, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10 years old nephew and he doesn't speak english yet, no problem! Just help us translate Board Game Arena into your language! == What can be translated ? == Every string of text for the mainsite interface and for the games interfaces is 'internationalized' and can be translated. For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometimes later... == Who should translate ? == This is important : only native speakers of a given language should translate in this language. When translating a game, the translator should know the game and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronomical rules usual for the gaming audience of their country. As Board Game Arena's team's mothertongue is french, we will take charge of the french translations. We will also release the first version of the english translation. As we are not perfect speakers of Shakespeare's language, these translation will be open for review and correction from native english speakers under the same conditions as the other languages. == About context == Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot uncorrect forms (if any) while playing and be able to correct them. Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information. == When will the site be made available in a new language it is being translated into ? == As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in this language. == I fixed some translations, but they don't appear to have changed on the site ? == Translation files are updated each time we do a new release, so you have to wait until the next BGA release for your changes to appear on the site. Usually this should happen every week or two. == How long will it be possible to change the translations ? == The first translations may not be perfect (as explained in the 'about context' section). So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore. == Is there some reward for translating ? == Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated). This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward among all! == Translation tips == Use the 'TAB' key to go from one text box to another. This is easier than clicking. Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}). When in doubt, leave a comment for the next translator. When you fix someone's translation, leave a comment if the reason for the change is not obvious. When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing. b99f4ae78569524581017328ac85c784a02229ee 43 42 2012-01-23T08:59:44Z Sourisdudesert 1 /* Translation tips */ wikitext text/x-wiki The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena in any language, in order to enable more people to discover and play boardgames, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10 years old nephew and he doesn't speak english yet, no problem! Just help us translate Board Game Arena into your language! == What can be translated ? == Every string of text for the mainsite interface and for the games interfaces is 'internationalized' and can be translated. For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometimes later... == Who should translate ? == This is important : only native speakers of a given language should translate in this language. When translating a game, the translator should know the game and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronomical rules usual for the gaming audience of their country. As Board Game Arena's team's mothertongue is french, we will take charge of the french translations. We will also release the first version of the english translation. As we are not perfect speakers of Shakespeare's language, these translation will be open for review and correction from native english speakers under the same conditions as the other languages. == About context == Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot uncorrect forms (if any) while playing and be able to correct them. Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information. == When will the site be made available in a new language it is being translated into ? == As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in this language. == I fixed some translations, but they don't appear to have changed on the site ? == Translation files are updated each time we do a new release, so you have to wait until the next BGA release for your changes to appear on the site. Usually this should happen every week or two. == How long will it be possible to change the translations ? == The first translations may not be perfect (as explained in the 'about context' section). So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore. == Is there some reward for translating ? == Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated). This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward among all! == Translation tips == * Use the 'TAB' key to go from one text box to another. This is easier than clicking. * Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}). * When in doubt, leave a comment for the next translator. * When you fix someone's translation, leave a comment if the reason for the change is not obvious. * When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing. 2ab2b11b7206e323ff840a76b8a125026e1e0344 Translationguidelines 0 19 44 2012-01-23T09:00:27Z Sourisdudesert 1 Redirected page to [[Translation Guidelines]] wikitext text/x-wiki #REDIRECT [[Translation Guidelines]] 08fc23949a4a226d9c81cccddc96fd7b9f4df0c0 45 44 2012-01-23T09:00:46Z Sourisdudesert 1 Redirected page to [[Translation guidelines]] wikitext text/x-wiki #REDIRECT [[Translation guidelines]] 9f3b026121a1f6a6e96bb1a66cffcbc391a612e0 MediaWiki:Sitenotice 8 20 46 2012-01-23T09:02:55Z Sourisdudesert 1 Created page with "<div style="font-size: 110%; background-color: ivory; padding: 0.5ex; border: 1px solid black; text-align: center;"> This is a documentation for [http://boardgamearena.com Boa..." wikitext text/x-wiki <div style="font-size: 110%; background-color: ivory; padding: 0.5ex; border: 1px solid black; text-align: center;"> This is a documentation for [http://boardgamearena.com Board Game Arena]: play board games online ! </div> eb809cbdb9e505f0fa399f3b2ceb6a38ecf4d423 Gamehelpstoneage 0 21 47 2012-01-23T09:11:20Z Sourisdudesert 1 Created page with " == Goal == Get the most victory points at the end of the game. You win some points: * during the game, by acquiring buildings. * at the end of the game, with your civilizat..." wikitext text/x-wiki == Goal == Get the most victory points at the end of the game. You win some points: * during the game, by acquiring buildings. * at the end of the game, with your civilization cards. == Rules summary == Each round is divided into 3 phases, which are executed in the order described: 1. The players place their people on the game board. 2. The players use the actions of their placed people. 3. The players feed their people. ===Place your people on the game board=== Players placed their people on "rings" (1 people per ring). Special rules with 2 players: * only 1 player in each of the following: forest, clay pit, quarry, and river. * only 2 of the 3 places: tool maker, hut, and field may be filled in each round. Special rules with 3 players: * maximum of 2 players in each of the following: forest, clay pit, quarry, and river. * only 2 of the 3 places: tool maker, hut, and field may be filled in each round. ===Use the actions of your placed people=== Each player uses all his placed people in any order, and realize the corresponding actions: * hunting grounds, forest, clay pit, quarry, and river: roll 1 dice per people and take corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river). * field: increase agriculture level. * tool: get one tool. * hut: get one additional people. * building: buy the building with resources and score points. * civilization card: buy the card with a number of resources depending on its position (1 to 4 resources). ===Resources=== hunting grounds, forest, clay pit, quarry, and river: Roll 1 dice per people and take corresponding resources: * 1 food for each full 2 on hunting grounds, * 1 wood for each full 3 on forest, * 1 brick for each full 4 on clay pit, * 1 stone for each full 5 on quarry, * 1 gold for each full 6 on river. You can use tool to increase the dice result and take more resources. ===Buildings=== Pay the building cost to get the building and receive points. If building cost is not specified you win points for each resources used depending on their values (3 for wood, 4 for brick, ...). ===Civilization card details=== Each card brings an immediate advantage (item on the top of the card) and some points during final scoring( item on the bottom of the card). Place the mouse cursor on each card to see details. ===Feed your people=== Each agriculture level bring automatically 1 food. You must use 1 food per people. You can use any resource to feed your people if there is not enough food. If you don't manage to feed your people: 10 points penalty. ===Game end=== The game end when: * there is no more civilization card at the beginning of a round * one building stack is empty at the end of a round During the final scoring round, players win points using their civilization cards. 34d16399aa3a8e5f4902df2ff48e9e81de1c043f Gamehelphaggis 0 22 48 2012-01-23T09:12:40Z Sourisdudesert 1 Created page with " == Goal == Empty your hand before the other players. Additional points may be earned by capturing cards during play and betting that you will be first to shed all of your ca..." wikitext text/x-wiki == Goal == Empty your hand before the other players. Additional points may be earned by capturing cards during play and betting that you will be first to shed all of your cards. == Rules summary == A valid card combination may be a set, a sequence or a bomb: * a "set" is a group of any number of cards of the same rank (ex: one "8", two "5", ...). * a "sequence" is a group of 3 or more cards of the same color with consecutive rank (ex: red 8, red 9, red 10) * a "sequence" can also be a group of 2 or more pairs or larger sets of consecutive rank sharing the same suits between sets (ex: blue 3, green 3, blue 4, green 4, blue 5, green 5) * a "bomb" is one of the following combination (ranked below from lowest to highest): ** 3-5-7-9 (in 4 different colors, "rainbow bomb") ** J-Q ** J-K ** Q-K ** J-Q-K ** 3-5-7-9 (in one color, "suited bomb") Face cards can be used as wild cards to replace any cards in a "set" or a "sequence". Each player starts a round with a Jack, a Queen and a King. These face cards are public. At your turn, you have to play a higher ranking combination with exactly the same type and same number of card that the first combination played. You can also pass. Bombs are an exception: you can play a bomb to beat any combination, except a higher bomb. When all but one player pass in succession, the player who played the highest combination capture all cards played. Important exception: if the highest combination is a bomb, cards are captured by the player with the next higher combination. Then, a new trick starts. The winner of the last trick leads the new trick with any combination. ===Scoring overview=== * At the moment you shed your last card: 5 points per card in the hand of the player who held the most cards. * Cards captured values: 2-4-6-8-10 = 0 point, 3-5-7-9 = 1 point, J = 2 points, Q = 3 points, K = 5 points. * 30 points for a successful "Big bet", 15 points for a successful "Little bet". Points from unsuccessful bets are added to scores of the round's winner and to player(s) who did not bet. da27e6a12b6310619db280f413a7b6b17f319f4f Gamehelppuertorico 0 23 49 2012-01-23T09:14:58Z Sourisdudesert 1 Created page with " == Goal == Be the player with the most victory points at the end of the game by collecting: * victory points earned for buildings * victory point tokens earned at the capta..." wikitext text/x-wiki == Goal == Be the player with the most victory points at the end of the game by collecting: * victory points earned for buildings * victory point tokens earned at the captain phase * conditional victory points earned at the end of the game for occupied large buildings In case of a tie, the player owning the most doubloons and goods is the winner. == Rules summary == The game is played over several rounds. At the start of a round, the governor selects a role, then each player in turn selects a role. At the end of the round, the governor token moves to the next player. When a role has been chosen, each player in turn plays the action for this role. Only the player who selected the role can use the role privilege. Available roles are the following: * Mayor: colonists set foot in the new world ! Privilege : the mayor can get one more colonist from the supply. Action : in turn, begining with the mayor, players get one colonist from the ship, until it is empty. Then players have to set colonists on their buildings and plantations. * Craftsman: goods are produced. Privilege : the craftsman can produce one more good of his choice. Action : produce goods for your occupied buildings and plantations. * Trader: goods are sold to the trading house. Privilege : the trader earns 1 extra doubloon if he sells. Action : sell one good the trading house doesn't have yet. * Settler : plantations settlement. Privilege : the settler can get a quarry instead of a plantation. Action : get a plantation chosen among those available. * Builder : buildings are bought and built. Privilege : the builder can get a building for 1 doubloon less than the regular price. Action : get a building chosen among those available. * Captain : victory points are won by shipping goods to the old world. Privilege : the captain earns one extra victory points if he ships some goods. Action : select a type of good to load on a cargo ship; 1 victory point is earned for each barrel of this type of good loaded on the ship. * Prospector : gold rush brings money ! Privilege : the prospector gets one doubloon from the bank. Action : none. Please also note that occupied violet buildings have modifier effects for role actions. End of game happens at the end of the round for which one of the following events comes to pass : * there is not enough colonists in the supply to refill the colonist ship at the end of the mayor phase * the last victory point token has been earned during the captain phase * at least one of the players built on his 12th and last free space in the city. == Playing online == Choosing a role : click on the role of your choice in the list on the right of your game board. Mayor role : accept or refuse to get an extra colonist from the supply. Colonists are then automatically recruited by players. Click on a building or a plantation to setup a colonist on it. Click on a colonist to send it back to San Juan (the counter for colonists in San Juan is situated in your player panel on the right of the page). Craftsman role : goods production is automated (counters for goods owned are in the player panel on the right of the page). Then, choose one extra good that you can produce as your privilege. Trader role : choose a good that you want to sell by clicking on the appropriate counter in your player panel. Settler role : click on the plantation (or quarry) that you want. Placement on your board is automated. Builder role : click on the building that you want to buy. Placement on your board is automated. Captain role : click on the cargo boat on which you want to ship some goods. Then choose the type of good that you want to ship by clicking on the appropriate counter in your player panel. At the end of the captain phase, if you have some goods to store (warehouse or windrose), click on the corresponding counter. Stored goods will be highlighted by a red frame. Prospector role : doubloon is earned immediately. Tooltips are available to give information on roles and buildings by hovering over game elements with the mouse. == Available variant == Balanced game: implements two game balance fixes giving each player an equal chance of winning as listed in the [http://en.wikipedia.org/wiki/Puerto_Rico_%28board_game%29 Puerto Rico (board game) Wikipedia page]. * The prices of the Factory and University buildings are swapped so that the Factory costs 8 doubloons and the University costs 7 doubloons * Any player that starts with a corn plantation starts with 1 doubloon less than the players that start with an indigo plantation. Have a good game ! 5a89fda7aa0b6e44383ce70410e470a81e1a8000 80 49 2012-03-11T14:46:48Z Een 3 wikitext text/x-wiki == Goal == Be the player with the most victory points at the end of the game by collecting: * victory points earned for buildings * victory point tokens earned at the captain phase * conditional victory points earned at the end of the game for occupied large buildings In case of a tie, the player owning the most doubloons and goods is the winner. == Rules summary == The game is played over several rounds. At the start of a round, the governor selects a role, then each player in turn selects a role. At the end of the round, the governor token moves to the next player. When a role has been chosen, each player in turn plays the action for this role. Only the player who selected the role can use the role privilege. Available roles are the following: * Mayor: colonists set foot in the new world ! Privilege : the mayor can get one more colonist from the supply. Action : in turn, begining with the mayor, players get one colonist from the ship, until it is empty. Then players have to set colonists on their buildings and plantations. * Craftsman: goods are produced. Privilege : the craftsman can produce one more good of his choice. Action : produce goods for your occupied buildings and plantations. * Trader: goods are sold to the trading house. Privilege : the trader earns 1 extra doubloon if he sells. Action : sell one good the trading house doesn't have yet. * Settler : plantations settlement. Privilege : the settler can get a quarry instead of a plantation. Action : get a plantation chosen among those available. * Builder : buildings are bought and built. Privilege : the builder can get a building for 1 doubloon less than the regular price. Action : get a building chosen among those available. * Captain : victory points are won by shipping goods to the old world. Privilege : the captain earns one extra victory points if he ships some goods. Action : select a type of good to load on a cargo ship; 1 victory point is earned for each barrel of this type of good loaded on the ship. * Prospector : gold rush brings money ! Privilege : the prospector gets one doubloon from the bank. Action : none. Please also note that occupied violet buildings have modifier effects for role actions. End of game happens at the end of the round for which one of the following events comes to pass : * there is not enough colonists in the supply to refill the colonist ship at the end of the mayor phase * the last victory point token has been earned during the captain phase * at least one of the players built on his 12th and last free space in the city. == Playing online == Choosing a role : click on the role of your choice in the list on the right of your game board. * Mayor role : accept or refuse to get an extra colonist from the supply. Colonists are then automatically recruited by players. Click on a building or a plantation to setup a colonist on it. Click on a colonist to send it back to San Juan (the counter for colonists in San Juan is situated in your player panel on the right of the page). * Craftsman role : goods production is automated (counters for goods owned are in the player panel on the right of the page). Then, choose one extra good that you can produce as your privilege. * Trader role : choose a good that you want to sell by clicking on the appropriate counter in your player panel. * Settler role : click on the plantation (or quarry) that you want. Placement on your board is automated. * Builder role : click on the building that you want to buy. Placement on your board is automated. * Captain role : click on the cargo boat on which you want to ship some goods. Then choose the type of good that you want to ship by clicking on the appropriate counter in your player panel. At the end of the captain phase, if you have some goods to store (warehouse or windrose), click on the corresponding counter. Stored goods will be highlighted by a red frame. * Prospector role : doubloon is earned immediately. Tooltips are available to give information on roles and buildings by hovering over game elements with the mouse. == 'Balanced game' variant == This variant implements two game balance fixes giving each player an equal chance of winning as listed in the [http://en.wikipedia.org/wiki/Puerto_Rico_%28board_game%29 Puerto Rico (board game) Wikipedia page]. * The prices of the Factory and University buildings are swapped so that the Factory costs 8 doubloons and the University costs 7 doubloons * Any player that starts with a corn plantation starts with 1 doubloon less than the players that start with an indigo plantation. '''Have a good game !''' 0b804619fb7d51434ad55e5ff5672a4cd2fdbba9 Gamehelpunclechestnuttablegype 0 24 50 2012-01-23T09:15:58Z Sourisdudesert 1 Created page with " == Goal == Move all of your pieces to the Home Row opposite your starting position. == Rules summary == On their turn, each player can: 1) Roll one of his pieces and plac..." wikitext text/x-wiki == Goal == Move all of your pieces to the Home Row opposite your starting position. == Rules summary == On their turn, each player can: 1) Roll one of his pieces and place it back where it was 2) Move one of the pieces according to the rules for the face-up side == Movement of the pieces: == * Flame: can move straight or diagonally in all directions * Book: can move straight in all directions * Swords: can move diagonnally in all directions * Tree: can move straight forward or backwards, and diagonally forward * Ear: cannot move at all ! * Hat: can move two steps straight then one step on the side, in all directions (like the knight in chess) A piece can jump over an adjacent piece if there is an open space on the other side of the piece being jumped in the direction of the jumping piece's movement. The first time a piece is jumped over during a turn, it has to be rolled. After a jump, all pieces (except for the hat) can go on jumping as long as there is another valid jump available from the landing space. A piece can freely move within its Home Row as long as it did not leave it. After it leaves though, it can't reenter its Home Row. A piece arrived into his destination Home Row cannot move afterwards. Nonetheless, it can always finish a series of jumps before coming to a rest. Playing online Reordering your pieces: before starting to play, each player can reorder his pieces in his Home Row. To accomplish this, you can drag and drop a piece over another to exchange their positions. When you are done, click on the 'I'm finished' link above the play space. When all players are finished reordering, the game starts. Select a piece: click on a piece. Available destinations for this piece (jumps comprised) are then highlighted. Move a piece: click on the destination you want to move to. After a jump, if it is possible to make another jump, corresponding destinations will be highlighted. You can also stop where you are by clicking on the 'I'm finished' link above the play space. Path selection: in order to move to a given destination, the hat can select between two moves. Either two steps forward then one on the side, or one step on the side then two steps forward. Distinct pieces may be rolled by following one path or another. Choosing the movement you want is done by clicking the link '1->2' or the link '2->1' (selected path is then highlighted), then by clicking the link 'I'm finished' above the play space. Available variants Random start: for a more random game, starting pieces are rolled (Ears are rolled again till getting only moving pieces). Rule of Chaos: to encourage more chaos, a player cannot cross the middle of the board with any of their pieces until their starting Home Row has been emptied: all pieces have to be put in play at the same time. Random start & Rule of Chaos : combination of the two previous variants. Have a good game ! 47a14dc24dc2483015390cae73fbdbd33cb69c3b 51 50 2012-01-23T09:16:52Z Sourisdudesert 1 wikitext text/x-wiki == Goal == Move all of your pieces to the Home Row opposite your starting position. == Rules summary == On their turn, each player can: * 1°) Roll one of his pieces and place it back where it was * 2°) Move one of the pieces according to the rules for the face-up side == Movement of the pieces: == * Flame: can move straight or diagonally in all directions * Book: can move straight in all directions * Swords: can move diagonnally in all directions * Tree: can move straight forward or backwards, and diagonally forward * Ear: cannot move at all ! * Hat: can move two steps straight then one step on the side, in all directions (like the knight in chess) A piece can jump over an adjacent piece if there is an open space on the other side of the piece being jumped in the direction of the jumping piece's movement. The first time a piece is jumped over during a turn, it has to be rolled. After a jump, all pieces (except for the hat) can go on jumping as long as there is another valid jump available from the landing space. A piece can freely move within its Home Row as long as it did not leave it. After it leaves though, it can't reenter its Home Row. A piece arrived into his destination Home Row cannot move afterwards. Nonetheless, it can always finish a series of jumps before coming to a rest. == Playing online == '''Reordering your pieces''': before starting to play, each player can reorder his pieces in his Home Row. To accomplish this, you can drag and drop a piece over another to exchange their positions. When you are done, click on the 'I'm finished' link above the play space. When all players are finished reordering, the game starts. '''Select a piece''': click on a piece. Available destinations for this piece (jumps comprised) are then highlighted. '''Move a piece''': click on the destination you want to move to. After a jump, if it is possible to make another jump, corresponding destinations will be highlighted. You can also stop where you are by clicking on the 'I'm finished' link above the play space. '''Path selection''': in order to move to a given destination, the hat can select between two moves. Either two steps forward then one on the side, or one step on the side then two steps forward. Distinct pieces may be rolled by following one path or another. Choosing the movement you want is done by clicking the link '1->2' or the link '2->1' (selected path is then highlighted), then by clicking the link 'I'm finished' above the play space. == Available variants == '''Random start''': for a more random game, starting pieces are rolled (Ears are rolled again till getting only moving pieces). '''Rule of Chaos''': to encourage more chaos, a player cannot cross the middle of the board with any of their pieces until their starting Home Row has been emptied: all pieces have to be put in play at the same time. '''Random start & Rule of Chaos''' : combination of the two previous variants. Have a good game ! e0e1c7bf1bdc07eca3c7b1aa2d2d463ff891abe4 79 51 2012-03-11T14:43:52Z Een 3 wikitext text/x-wiki == Goal == Move all of your pieces to the Home Row opposite your starting position. == Rules summary == On their turn, each player can: # Roll one of his pieces and place it back where it was # Move one of the pieces according to the rules for the face-up side == Movement of the pieces: == * Flame: can move straight or diagonally in all directions * Book: can move straight in all directions * Swords: can move diagonnally in all directions * Tree: can move straight forward or backwards, and diagonally forward * Ear: cannot move at all ! * Hat: can move two steps straight then one step on the side, in all directions (like the knight in chess) A piece can jump over an adjacent piece if there is an open space on the other side of the piece being jumped in the direction of the jumping piece's movement. The first time a piece is jumped over during a turn, it has to be rolled. After a jump, all pieces (except for the hat) can go on jumping as long as there is another valid jump available from the landing space. A piece can freely move within its Home Row as long as it did not leave it. After it leaves though, it can't reenter its Home Row. A piece arrived into his destination Home Row cannot move afterwards. Nonetheless, it can always finish a series of jumps before coming to a rest. == Playing online == '''Reordering your pieces''': before starting to play, each player can reorder his pieces in his Home Row. To accomplish this, you can drag and drop a piece over another to exchange their positions. When you are done, click on the 'I'm finished' link above the play space. When all players are finished reordering, the game starts. '''Select a piece''': click on a piece. Available destinations for this piece (jumps comprised) are then highlighted. '''Move a piece''': click on the destination you want to move to. After a jump, if it is possible to make another jump, corresponding destinations will be highlighted. You can also stop where you are by clicking on the 'I'm finished' link above the play space. '''Path selection''': in order to move to a given destination, the hat can select between two moves. Either two steps forward then one on the side, or one step on the side then two steps forward. Distinct pieces may be rolled by following one path or another. Choosing the movement you want is done by clicking the link '1->2' or the link '2->1' (selected path is then highlighted), then by clicking the link 'I'm finished' above the play space. == Available variants == '''Random start''': for a more random game, starting pieces are rolled (Ears are rolled again till getting only moving pieces). '''Rule of Chaos''': to encourage more chaos, a player cannot cross the middle of the board with any of their pieces until their starting Home Row has been emptied: all pieces have to be put in play at the same time. '''Random start & Rule of Chaos''' : combination of the two previous variants. '''Have a good game !''' cf24749138ddb9e1bb14c0a6a3ff344a8f7e2684 Gamehelpgosu 0 25 52 2012-01-23T09:19:41Z Sourisdudesert 1 Created page with "Need some help ? Join [http://www.gosulair.fr/index.php Gosu player's community on Gosulair.fr] == Victory == You win when you have 3 Victory Points or when you complete a s..." wikitext text/x-wiki Need some help ? Join [http://www.gosulair.fr/index.php Gosu player's community on Gosulair.fr] == Victory == You win when you have 3 Victory Points or when you complete a special victory condition. == Rules summary == During the Round, players play in turns, clockwise. The player with the Advantage Token starts to play. When all players have passed, the Round ends and the Great Battle takes place. ===Great Battle=== Add up the military value of all your goblins. The owner of the most powerful army wins the Battle and scores a Victory Point. In case of a tie during the Battle, the player with the Advantage Token wins. All armies stay put and the players keep their hand of cards. ===One turn, one action=== * Play a goblin. * Mutate a goblin. * Spend 1 Activation Token to draw 1 card. * Spend 2 Activation Tokens to draw 3 cards. * Play an Activation Token on a goblin to activate its power (only 1 Token allowed per card). * Pass (the player who pass has no turn until the next Round.). ===Goblins=== Every goblin in a Level are played from left to right in one row. Rows are ordered by ascending level from the bottom to the top. You can't play more than 5 goblins per row. '''Bakutos (level I)''' * The first Bakuto is always free. * Play a Bakuto is free if a Bakuto from the same clan is already in play. * To play a Bakuto from a new clan, you have to discard 2 cards. '''Heroes (level II)''' * No more Heroes than Bakutos. * In order to play a Hero, a Bakuto from the same clan must be in your army (no need to have him above the Bakuto). '''Ōzekis (level III)''' * No more Ōzekis than Heroes. * In order to play an Ōzeki, a Hero and a Bakuto from the same clan must be in your army. ===Mutation=== You can mutate a goblin in another different goblin on the same Level if you pay the Mutation Cost of the card: Name the card to mutate. Name et set aside the card that comes into play. Discard the mutated card. Apply any triggered effect. Play the mutating card. Apply any triggered effect. Resolve Mutating effect. A mutated carte is not « destroyed ». Zombie Mutation: the mutating goblin may come from the discard pile. Goblins powers & details A FREE card has no cards above nor on its right. Carte emprisonnée : retournée, elle n'a ni pouvoir ni valeur militaire ni clan, mais conserve son nom et sa place dans l'armée. Costs : the card costs (play, mutate, ...) are payed with cards discarded from your hand. When the draw pile is empty and you have to draw, you shuffle the discard pile and make it the new draw pile. The bonus mentionned into brackets (+...) apply if some opponent has more victory points. The discard pile receive the discarded, destroyed or mutated cards. Any player can browse it anytime. If a player wins his third Victory Point in a Round, he wins the game immediatly. Board Game Arena would like to thanks mAxAttAck de gosulair.fr for this game help. 6b6358222feb2e53c7791d8d0c33a17076519651 53 52 2012-01-23T09:20:49Z Sourisdudesert 1 wikitext text/x-wiki Need some help ? Join [http://www.gosulair.fr/index.php Gosu player's community on Gosulair.fr] == Victory == You win when you have 3 Victory Points or when you complete a special victory condition. == Rules summary == During the Round, players play in turns, clockwise. The player with the Advantage Token starts to play. When all players have passed, the Round ends and the Great Battle takes place. ===Great Battle=== Add up the military value of all your goblins. The owner of the most powerful army wins the Battle and scores a Victory Point. In case of a tie during the Battle, the player with the Advantage Token wins. All armies stay put and the players keep their hand of cards. ===One turn, one action=== * Play a goblin. * Mutate a goblin. * Spend 1 Activation Token to draw 1 card. * Spend 2 Activation Tokens to draw 3 cards. * Play an Activation Token on a goblin to activate its power (only 1 Token allowed per card). * Pass (the player who pass has no turn until the next Round.). ===Goblins=== Every goblin in a Level are played from left to right in one row. Rows are ordered by ascending level from the bottom to the top. You can't play more than 5 goblins per row. '''Bakutos (level I)''' * The first Bakuto is always free. * Play a Bakuto is free if a Bakuto from the same clan is already in play. * To play a Bakuto from a new clan, you have to discard 2 cards. '''Heroes (level II)''' * No more Heroes than Bakutos. * In order to play a Hero, a Bakuto from the same clan must be in your army (no need to have him above the Bakuto). '''Ōzekis (level III)''' * No more Ōzekis than Heroes. * In order to play an Ōzeki, a Hero and a Bakuto from the same clan must be in your army. ===Mutation=== You can mutate a goblin in another different goblin on the same Level if you pay the Mutation Cost of the card: * Name the card to mutate. * Name et set aside the card that comes into play. * Discard the mutated card. * Apply any triggered effect. * Play the mutating card. * Apply any triggered effect. * Resolve Mutating effect. A mutated carte is not « destroyed ». Zombie Mutation: the mutating goblin may come from the discard pile. ===Goblins powers & details=== A FREE card has no cards above nor on its right. Trapped card : no power, no value, no clan. It keeps its name and its place in the army. Costs : the card costs (play, mutate, ...) are payed with cards discarded from your hand. When the draw pile is empty and you have to draw, you shuffle the discard pile and make it the new draw pile. The bonus mentionned into brackets (+...) apply if some opponent has more victory points. The discard pile receive the discarded, destroyed or mutated cards. Any player can browse it anytime. If a player wins his third Victory Point in a Round, he wins the game immediatly. Board Game Arena would like to thanks mAxAttAck de gosulair.fr for this game help. 2de59874bb4c8b039c82523b624075e1a4da29c1 66 53 2012-02-06T01:12:27Z Jleidich 100 /* Mutation */ wikitext text/x-wiki Need some help ? Join [http://www.gosulair.fr/index.php Gosu player's community on Gosulair.fr] == Victory == You win when you have 3 Victory Points or when you complete a special victory condition. == Rules summary == During the Round, players play in turns, clockwise. The player with the Advantage Token starts to play. When all players have passed, the Round ends and the Great Battle takes place. ===Great Battle=== Add up the military value of all your goblins. The owner of the most powerful army wins the Battle and scores a Victory Point. In case of a tie during the Battle, the player with the Advantage Token wins. All armies stay put and the players keep their hand of cards. ===One turn, one action=== * Play a goblin. * Mutate a goblin. * Spend 1 Activation Token to draw 1 card. * Spend 2 Activation Tokens to draw 3 cards. * Play an Activation Token on a goblin to activate its power (only 1 Token allowed per card). * Pass (the player who pass has no turn until the next Round.). ===Goblins=== Every goblin in a Level are played from left to right in one row. Rows are ordered by ascending level from the bottom to the top. You can't play more than 5 goblins per row. '''Bakutos (level I)''' * The first Bakuto is always free. * Play a Bakuto is free if a Bakuto from the same clan is already in play. * To play a Bakuto from a new clan, you have to discard 2 cards. '''Heroes (level II)''' * No more Heroes than Bakutos. * In order to play a Hero, a Bakuto from the same clan must be in your army (no need to have him above the Bakuto). '''Ōzekis (level III)''' * No more Ōzekis than Heroes. * In order to play an Ōzeki, a Hero and a Bakuto from the same clan must be in your army. ===Mutation=== You can mutate a goblin in another different goblin on the same Level if you pay the Mutation Cost of the card: * Name the card to mutate. * Name and set aside the card that comes into play. * Discard the mutated card. * Apply any triggered effect. * Play the mutating card. * Apply any triggered effect. * Resolve Mutating effect. A mutated card is not « destroyed ». Zombie Mutation: the mutating goblin may come from the discard pile. ===Goblins powers & details=== A FREE card has no cards above nor on its right. Trapped card : no power, no value, no clan. It keeps its name and its place in the army. Costs : the card costs (play, mutate, ...) are payed with cards discarded from your hand. When the draw pile is empty and you have to draw, you shuffle the discard pile and make it the new draw pile. The bonus mentionned into brackets (+...) apply if some opponent has more victory points. The discard pile receive the discarded, destroyed or mutated cards. Any player can browse it anytime. If a player wins his third Victory Point in a Round, he wins the game immediatly. Board Game Arena would like to thanks mAxAttAck de gosulair.fr for this game help. a62e06b222c75ef7b96e85f1dc657b36d24fcd85 67 66 2012-02-06T01:14:28Z Jleidich 100 /* Goblins powers & details */ wikitext text/x-wiki Need some help ? Join [http://www.gosulair.fr/index.php Gosu player's community on Gosulair.fr] == Victory == You win when you have 3 Victory Points or when you complete a special victory condition. == Rules summary == During the Round, players play in turns, clockwise. The player with the Advantage Token starts to play. When all players have passed, the Round ends and the Great Battle takes place. ===Great Battle=== Add up the military value of all your goblins. The owner of the most powerful army wins the Battle and scores a Victory Point. In case of a tie during the Battle, the player with the Advantage Token wins. All armies stay put and the players keep their hand of cards. ===One turn, one action=== * Play a goblin. * Mutate a goblin. * Spend 1 Activation Token to draw 1 card. * Spend 2 Activation Tokens to draw 3 cards. * Play an Activation Token on a goblin to activate its power (only 1 Token allowed per card). * Pass (the player who pass has no turn until the next Round.). ===Goblins=== Every goblin in a Level are played from left to right in one row. Rows are ordered by ascending level from the bottom to the top. You can't play more than 5 goblins per row. '''Bakutos (level I)''' * The first Bakuto is always free. * Play a Bakuto is free if a Bakuto from the same clan is already in play. * To play a Bakuto from a new clan, you have to discard 2 cards. '''Heroes (level II)''' * No more Heroes than Bakutos. * In order to play a Hero, a Bakuto from the same clan must be in your army (no need to have him above the Bakuto). '''Ōzekis (level III)''' * No more Ōzekis than Heroes. * In order to play an Ōzeki, a Hero and a Bakuto from the same clan must be in your army. ===Mutation=== You can mutate a goblin in another different goblin on the same Level if you pay the Mutation Cost of the card: * Name the card to mutate. * Name and set aside the card that comes into play. * Discard the mutated card. * Apply any triggered effect. * Play the mutating card. * Apply any triggered effect. * Resolve Mutating effect. A mutated card is not « destroyed ». Zombie Mutation: the mutating goblin may come from the discard pile. ===Goblins powers & details=== A FREE card has no cards above it nor to its right. Trapped card : no power, no value, no clan. It keeps its name and place in the army. Costs : the card costs (play, mutate, ...) are payed with cards discarded from your hand. When the draw pile is empty and you have to draw, you shuffle the discard pile and make it the new draw pile. The bonus mentioned in brackets (+...) apply if some opponent has more victory points. The discard pile receives the discarded, destroyed or mutated cards. Any player can browse it anytime. If a player wins his third Victory Point in a Round, he wins the game immediatly. Board Game Arena would like to thanks mAxAttAck de gosulair.fr for this game help. aeee202f11e1fef25f50b04ff56e9895ee5263d2 Gamehelptroyes 0 26 54 2012-01-23T09:25:01Z Sourisdudesert 1 Created page with " == Goal == Be the player with the most victory points at the end of the game. == Rules summary == (This rules summary is based on the game help written by [http://boardgam..." wikitext text/x-wiki == Goal == Be the player with the most victory points at the end of the game. == Rules summary == (This rules summary is based on the game help written by [http://boardgamegeek.com/user/pregremlin Andrew Agard] for Board Game Geek, under Creative Commons license. Please see [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] here for details. Thank you Andrew !) ===Initial Placement=== * In clockwise order place a citizen in empty space of one building * Continue in counter clockwise order from last player and so on until all citizens placed ===Game play=== ====Phase 0: Reveal the Activity cards==== Reveal activity card for each color corresponding to current round (first 3 rounds only) ====Phase 1: Income and salaries==== Receive 10 deniers and pay 1 per Bishopric and 2 per Palace citizen or lose 2 VP ====Phase 2: Assembling the workforce==== Roll yellow/white/red die per citizen in City Hall/Bishopric/Palace and place in district ====Phase 3: Events==== Reveal top red and white or yellow Event and place to right of queue (unlimited Events) Events take effect from left to right * Military: start player takes 1 black die per die symbol * Other events: see annex (can’t execute: execute as much as possible and lose 2 VP) After Events, roll black dice and counter: * Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once * Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP) * In order players must counter highest remaining until all countered * Use any color dice. Double red dice. Can’t buy dice or use activity cubes ====Phase 4: Actions==== See below. ====Phase 5: End of the round==== Receive deniers from district Return citizens lying on buildings to personal supplies Return unused dice to general supply Pass start player card left. ===Actions=== In order each player can use 1-3 matching dice for one action or pass. Round ends when no dice available or all players have passed May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice ====Activate Activity Card==== Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place citizen on free space (or illustration if full) from personal supply or any board location * 1 tradesman per player per card * Must activate at least once if tradesman hired * Citizens on card cannot be moved to newly freed space Immediate effect: activation cost (round down) determines color and use of dice Delayed effect: place cubes equal to activation cost. Use later (one cube per action) ====Construct Cathedral==== * Use 1-3 white dice to place 1-3 cubes on same-numbered construction site * Must place on lower levels before placing in higher levels for each set of valued spaces * Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6 ====Combat Events==== * Activation cost (round down) defines dice and number of cubes to place on card * Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners Event countered when banners filled * Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards. * 2nd most cubes earns smaller reward (tied: total rounded down) * Most cubes takes card (tied: player who placed first). Discard if neutral has most * Marauding: rewards given, cubes removed, and then event is available again ====Place a citizen on building==== * Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value * Shift existing citizens to right. Citizens pushed off are laid on building illustration * If already have expelled citizen nobody can expel your citizens from that building ====Use Agriculture==== * Gain number of deniers equal to total value divided by 2 (round down) ===Pass=== * If dice still in any city square, pass and receive 2 deniers which are placed in district * Each turn add another denier to district Have a good game ! fbdfaed8129e77bd038dee3623968940c24674a0 Gamehelptobago 0 27 55 2012-01-23T09:26:14Z Sourisdudesert 1 Created page with " == Goal == Get as many gold coins as you can by locating treasures on the Tobago island and sharing them with other players. == Rules summary == On their turn, each player..." wikitext text/x-wiki == Goal == Get as many gold coins as you can by locating treasures on the Tobago island and sharing them with other players. == Rules summary == On their turn, each player can choose one of two actions: ===1) Play a clue card from his hand=== The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue). Positioning clues are as follows: in, next to, in sight of, not in, not next to, not is sight of. When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type. When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map indicate show where the treasure can be. When there is only one of these markers left, the treasure is located and can be raised. ===2) Move ATV from 1 to 3 legs=== A leg is a move of: * either as many spaces as you want in the same land type * or one space only when your ATV goes from one land type to another. When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. When a treasure is raised, the current move is finished, even if the player has not used all the legs to which he was entitled. Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure. Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards. An additional card is taken from the deck and the cards are shuffled. Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded. Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card. When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map. Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base. Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions: * play a clue card * remove a treasure marker * move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet) * to exchange the clue cards from his hand with clue cards from the deck Proper use of amulet power is critical to ensure victory! The game ends after sharing the treasure for which the deck of treasure cards has been exhausted. Have a good game ! 1cf926fcbeaf776e08a8d7a0e3228b35b9f0c542 81 55 2012-03-11T14:48:48Z Een 3 wikitext text/x-wiki == Goal == Get as many gold coins as you can by locating treasures on the Tobago island and sharing them with other players. == Rules summary == On their turn, each player can choose one of two actions: ===1) Play a clue card from his hand=== The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue). Positioning clues are as follows: in, next to, in sight of, not in, not next to, not is sight of. When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type. When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map indicate show where the treasure can be. When there is only one of these markers left, the treasure is located and can be raised. ===2) Move ATV from 1 to 3 legs=== A leg is a move of: * either as many spaces as you want in the same land type * or one space only when your ATV goes from one land type to another. When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. When a treasure is raised, the current move is finished, even if the player has not used all the legs to which he was entitled. Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure. Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards. An additional card is taken from the deck and the cards are shuffled. Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded. Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card. When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map. Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base. Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions: * play a clue card * remove a treasure marker * move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet) * to exchange the clue cards from his hand with clue cards from the deck Proper use of amulet power is critical to ensure victory! The game ends after sharing the treasure for which the deck of treasure cards has been exhausted. '''Have a good game !''' b3a0671ef523f43497b67a815ac6f839a04dbd1b 87 81 2012-03-31T00:48:04Z Avron 453 /* 1) Play a clue card from his hand */ wikitext text/x-wiki == Goal == Get as many gold coins as you can by locating treasures on the Tobago island and sharing them with other players. == Rules summary == On their turn, each player can choose one of two actions: ===1) Play a clue card from his hand=== The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue). Positioning clues are as follows: in, next to, in sight of, not in, not next to, not in sight of. When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type. When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map indicate where the treasure can be. When there is only one of these markers left, the treasure is located and can be raised. ===2) Move ATV from 1 to 3 legs=== A leg is a move of: * either as many spaces as you want in the same land type * or one space only when your ATV goes from one land type to another. When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. When a treasure is raised, the current move is finished, even if the player has not used all the legs to which he was entitled. Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure. Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards. An additional card is taken from the deck and the cards are shuffled. Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded. Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card. When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map. Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base. Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions: * play a clue card * remove a treasure marker * move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet) * to exchange the clue cards from his hand with clue cards from the deck Proper use of amulet power is critical to ensure victory! The game ends after sharing the treasure for which the deck of treasure cards has been exhausted. '''Have a good game !''' 1ce82af1085c3662b22e442d6634e1ed2c342517 Gamehelpamyitis 0 28 56 2012-01-23T09:29:49Z Sourisdudesert 1 Created page with " == Victory == The player with the most victory points (VP) wins the game. == Rules summary == Thank you [http://boardgamegeek.com/user/sdetoni Steven] for this game help ..." wikitext text/x-wiki == Victory == The player with the most victory points (VP) wins the game. == Rules summary == Thank you [http://boardgamegeek.com/user/sdetoni Steven] for this game help (original file is [http://boardgamegeek.com/filepage/64197/synopses-of-amyitis-rules there]). Game starts, and recycles the 3 phases, setup, action, maintenance, until: * 4 or less garden tiles are left after a maintenance phase for 3/4 players. * 3 or less garden tiles are left after a maintenance phase for 2 players. ===Setup Phase=== Shuffle all Craftsmen cards and Layout as below. * 2 players: 2 groups of three cards. * 3 players: 3 groups of three cards. * 4 players: 4 groups of three cards. Players with Bankers earn Income (1 coin, 2 coins, or 2 coins & 2 VPs). ===Action Phase=== '''Passing''' Place cube on Pass space; each time that player Passes afterward, he earns 1 coin. '''Purchasing Workers''' Recruit a Craftsman from a set; the first in a set (3 horizontal cards) costs no coins, the second cost 1 coin, and the third costs 2 coins. Turn over card to display coin upon chosen card, which signifies the cost of the next card. Merchant: Take 1 camel into the players supply. Engineer: Place 1 cube of a player on an irrigation marker and get 2 VPs. The cube placement must trace an unbroken path of irrigation cubes to the river. Priest: Place 1 cube of a player into one Temple’s line of petitioners (each Temple will earn something in the Maintenance Phase). Place cube from left and shift all other cubes to the right. Cubes that drop off from the right are placed back into supply. Farmer: Place 1 cube of a player on the left most open field space and take that Resource into Supply. If that Resource is Wine, the field is cleared and whoever had a majority of cubes in that field gets a Gardener card if one is available. If tied, the cube colour furthest to the right wins the gardener card. '''Trading/Caravanning''' Move the Caravan by paying at least 1 Camel token and moving as many spaces as Camels paid plus up to as many spaces as allowed by the current Caravan card. A Caravan cannot be moved to a place where a player cannot fulfil the demands of that city. If the Caravan moves into Babylon either 1 Resource token must be given up for 3 VPs or 2 resource tokens can be given for 6 VPs; that player also places one irrigation cube. In some cities a player can hire Bankers and Caravaneers, as well as expand their Palace (bonus one-time VPs are added when cards are purchased). Pay the required resource to acquire these upgrade cards. In four of the cities there are Plants available. Some Plants are better than others and cost more (i.e. 2 resource tokens instead of 1). There are four levels to the Hanging Gardens, with level 1 Plants being able to be planted on its first level. Level 2 Plants may also be planted in level 1 Hanging Gardens. Gardeners can improve a Plant’s quality, allowing level 1 Plants to be planted on the Wonder’s second level or even its third; or allowing a level 2 Plant to be planted on the third level. That is, 1 or more gardener cards can be used on a plant to increases its quality. The Hanging Gardens’ fourth level requires a level 3 plant only. As soon as Plants are paid for, they are planted. The player who bought the Plant gains the prizes on the Wonder’s tile. A player who controls the irrigation around that tile (i.e. the most number of their colour cubes) scores VPs equal to the Plant’s initial level (not including spent gardener cards). If there is tie, then no VPs are given. Neutral grey cubes are added to empty irrigation spots of adjacent planted tile areas. Once bonuses and VPs have been award, the plant card is turned over in the caravan board to show a different plant on offer for that city/area. ===Maintenance Phase=== Temple Procession is controlled by the last player in the round; they place 1 cube of that players colour into one of the Temples of their choice, and 1 neutral cube into each of the other temples (i.e. 2 grey cubes total). Temples provide benefits to 1 player in a 2 player game, or 2 players in a 3-4 player game; ties for majority are broken by whose cube is closest to the right/exit. Award bonuses for each temple: Ishtar 1st Gets choice of a camel token or a coin. 2nd Gets what the 1st place didn’t want. Marduk 1st Gets 2 VPs. 2nd Gets 1 VPs. Tammouz 1st Gets to add a clue to the resource field of their choice. 2nd Gets to swap one of their resource tokens from supply, but not for wine. Players check goods in their Supply for resource spoilage and adjust the token number they can keep between major game rounds. Level 0,1 Caravaneers can keep up to 2 resource tokens. Level 2 Caravaneers can keep up to 4 resource tokens. The Starting Player card is passed clockwise. Re-shuffle craftsmen cards; go to setup phase to complete another game round. ===End Game=== Game ends when the follow conditions are met for the number people playing. 2 Players: When 3 garden tiles are left or less at the end of major game round. 5 or 6 Wonder tiles gained add additional 5 VPs, 7 Wonder tiles gained, add 10 VPs. 3 Players: When 4 garden tiles are left or less at the end of major game round. 4 or 5 Wonder tiles gained add additional 5 VPs, 6 Wonder tiles gained, add 10 VPs. 4 Players: When 4 garden tiles are left or less at the end of major game round. 3 or 4 Wonder tiles gained add additional 5 VPs, 5 Wonder tiles gained, add 10 VPs. Each player scores 1 additional VP for each resource token remaining in his stock (nothing for the camels and the coins). Total points = Current VPs + Resources Token Left + Bonus for number of garden tiles planted. 7f310513787f643d738ab499101925bd3ba58b17 Translation guidelines 0 18 57 43 2012-01-23T18:24:35Z Een 3 /* I fixed some translations, but they don't appear to have changed on the site ? */ wikitext text/x-wiki The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena in any language, in order to enable more people to discover and play boardgames, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10 years old nephew and he doesn't speak english yet, no problem! Just help us translate Board Game Arena into your language! == What can be translated ? == Every string of text for the mainsite interface and for the games interfaces is 'internationalized' and can be translated. For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometimes later... == Who should translate ? == This is important : only native speakers of a given language should translate in this language. When translating a game, the translator should know the game and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronomical rules usual for the gaming audience of their country. As Board Game Arena's team's mothertongue is french, we will take charge of the french translations. We will also release the first version of the english translation. As we are not perfect speakers of Shakespeare's language, these translation will be open for review and correction from native english speakers under the same conditions as the other languages. == About context == Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot uncorrect forms (if any) while playing and be able to correct them. Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information. == When will the site be made available in a new language it is being translated into ? == As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in this language. == I fixed some translations, but they don't appear to have changed on the site ? == Translation files are updated by a nightly batch, so you just have to wait till the morrow for your changes to appear on the site. == How long will it be possible to change the translations ? == The first translations may not be perfect (as explained in the 'about context' section). So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore. == Is there some reward for translating ? == Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated). This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward among all! == Translation tips == * Use the 'TAB' key to go from one text box to another. This is easier than clicking. * Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}). * When in doubt, leave a comment for the next translator. * When you fix someone's translation, leave a comment if the reason for the change is not obvious. * When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing. f7af8e4384b62aa3f98aed12555045fe22559d9a 63 57 2012-01-28T05:00:40Z Azraeldeadlight 63 /* Who should translate ? */ wikitext text/x-wiki The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena in any language, in order to enable more people to discover and play boardgames, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10 years old nephew and he doesn't speak english yet, no problem! Just help us translate Board Game Arena into your language! == What can be translated ? == Every string of text for the mainsite interface and for the games interfaces is 'internationalized' and can be translated. For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometimes later... == Who should translate ? == This is important: only native speakers of a given language should translate in this language. When translating a game, the translator should know the game and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronominal rules usual for the gaming audience of their country. As Board Game Arena's team's mother tongue is French, we will take charge of the French translations. We will also release the first version of the English translation. As we are not perfect speakers of Shakespeare's language, these translations will be open for review and correction by native English speakers under the same conditions as the other languages. == About context == Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot uncorrect forms (if any) while playing and be able to correct them. Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information. == When will the site be made available in a new language it is being translated into ? == As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in this language. == I fixed some translations, but they don't appear to have changed on the site ? == Translation files are updated by a nightly batch, so you just have to wait till the morrow for your changes to appear on the site. == How long will it be possible to change the translations ? == The first translations may not be perfect (as explained in the 'about context' section). So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore. == Is there some reward for translating ? == Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated). This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward among all! == Translation tips == * Use the 'TAB' key to go from one text box to another. This is easier than clicking. * Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}). * When in doubt, leave a comment for the next translator. * When you fix someone's translation, leave a comment if the reason for the change is not obvious. * When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing. 03a81a5f108268605fffaeaf1179a98eeeed1e12 68 63 2012-02-07T07:32:09Z Laszlosaurus 116 Great idea to wikify everything! wikitext text/x-wiki The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena into any language, in order to enable more people to discover and play board games, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10-year-old nephew and he doesn't speak English yet, no problem! Just help us translate Board Game Arena into your language! == What can be translated? == Every string of text for the main site interface and for the games' interfaces are 'internationalized' and can be translated. For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometime later... == Who should translate? == This is important: only translate text into a given language if you are a native speaker of the language. When translating a game, the translator should know the game thoroughly and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronominal rules usual for the gaming audience of their country. As Board Game Arena's team's mother tongue is French, we will take charge of the French translations. We will also release the first version of the English translation. As we are not perfect speakers of Shakespeare's language, these translations will be open for review and correction by native English speakers under the same conditions as the other languages. == About context == Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot incorrect forms (if any) while playing and be able to correct them. Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information. == When will the site be made available in a new language it is being translated into? == As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in the language. == I fixed some translations, but they don't appear to have changed on the site == Translation files are updated nightly, so you just have to wait till the morrow for your changes to appear on the site. == How long will it be possible to change the translations? == The first translations may not be perfect (as explained in the 'about context' section). So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore. == Is there some reward for translating? == Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated). This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all! == Translation tips == * Use the 'TAB' key to go from one text box to another. This is easier than clicking. * Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}). * When in doubt, leave a comment for the next translator. * When you fix someone's translation, leave a comment if the reason for the change is not obvious. * When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing. 5342971093e24707f58f475c7b88ca60b9f6c8e5 Gamehelpstoneage 0 21 58 47 2012-01-26T03:44:39Z Oedin 35 /* Game end */ wikitext text/x-wiki == Goal == Get the most victory points at the end of the game. You win some points: * during the game, by acquiring buildings. * at the end of the game, with your civilization cards. == Rules summary == Each round is divided into 3 phases, which are executed in the order described: 1. The players place their people on the game board. 2. The players use the actions of their placed people. 3. The players feed their people. ===Place your people on the game board=== Players placed their people on "rings" (1 people per ring). Special rules with 2 players: * only 1 player in each of the following: forest, clay pit, quarry, and river. * only 2 of the 3 places: tool maker, hut, and field may be filled in each round. Special rules with 3 players: * maximum of 2 players in each of the following: forest, clay pit, quarry, and river. * only 2 of the 3 places: tool maker, hut, and field may be filled in each round. ===Use the actions of your placed people=== Each player uses all his placed people in any order, and realize the corresponding actions: * hunting grounds, forest, clay pit, quarry, and river: roll 1 dice per people and take corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river). * field: increase agriculture level. * tool: get one tool. * hut: get one additional people. * building: buy the building with resources and score points. * civilization card: buy the card with a number of resources depending on its position (1 to 4 resources). ===Resources=== hunting grounds, forest, clay pit, quarry, and river: Roll 1 dice per people and take corresponding resources: * 1 food for each full 2 on hunting grounds, * 1 wood for each full 3 on forest, * 1 brick for each full 4 on clay pit, * 1 stone for each full 5 on quarry, * 1 gold for each full 6 on river. You can use tool to increase the dice result and take more resources. ===Buildings=== Pay the building cost to get the building and receive points. If building cost is not specified you win points for each resources used depending on their values (3 for wood, 4 for brick, ...). ===Civilization card details=== Each card brings an immediate advantage (item on the top of the card) and some points during final scoring( item on the bottom of the card). Place the mouse cursor on each card to see details. ===Feed your people=== Each agriculture level bring automatically 1 food. You must use 1 food per people. You can use any resource to feed your people if there is not enough food. If you don't manage to feed your people: 10 points penalty. ===Game end=== The game ends when: * there are no more civilization cards at the beginning of a round * one building stack is empty at the end of a round During the final scoring round, players win points using their civilization cards. f95d7d0ce2d15cea166eddeeb542ba0fc8c1d59c 59 58 2012-01-26T03:46:04Z Oedin 35 /* Feed your people */ wikitext text/x-wiki == Goal == Get the most victory points at the end of the game. You win some points: * during the game, by acquiring buildings. * at the end of the game, with your civilization cards. == Rules summary == Each round is divided into 3 phases, which are executed in the order described: 1. The players place their people on the game board. 2. The players use the actions of their placed people. 3. The players feed their people. ===Place your people on the game board=== Players placed their people on "rings" (1 people per ring). Special rules with 2 players: * only 1 player in each of the following: forest, clay pit, quarry, and river. * only 2 of the 3 places: tool maker, hut, and field may be filled in each round. Special rules with 3 players: * maximum of 2 players in each of the following: forest, clay pit, quarry, and river. * only 2 of the 3 places: tool maker, hut, and field may be filled in each round. ===Use the actions of your placed people=== Each player uses all his placed people in any order, and realize the corresponding actions: * hunting grounds, forest, clay pit, quarry, and river: roll 1 dice per people and take corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river). * field: increase agriculture level. * tool: get one tool. * hut: get one additional people. * building: buy the building with resources and score points. * civilization card: buy the card with a number of resources depending on its position (1 to 4 resources). ===Resources=== hunting grounds, forest, clay pit, quarry, and river: Roll 1 dice per people and take corresponding resources: * 1 food for each full 2 on hunting grounds, * 1 wood for each full 3 on forest, * 1 brick for each full 4 on clay pit, * 1 stone for each full 5 on quarry, * 1 gold for each full 6 on river. You can use tool to increase the dice result and take more resources. ===Buildings=== Pay the building cost to get the building and receive points. If building cost is not specified you win points for each resources used depending on their values (3 for wood, 4 for brick, ...). ===Civilization card details=== Each card brings an immediate advantage (item on the top of the card) and some points during final scoring( item on the bottom of the card). Place the mouse cursor on each card to see details. ===Feed your people=== Each agriculture level automatically give you 1 food. You must use 1 food per person. You can use any resource to feed your people if there is not enough food. If you don't manage to feed your people, you lose 10 points as a penalty. ===Game end=== The game ends when: * there are no more civilization cards at the beginning of a round * one building stack is empty at the end of a round During the final scoring round, players win points using their civilization cards. aa2efd8d0fcce02506a62d8dae4e1b0669bb8239 60 59 2012-01-26T03:47:06Z Oedin 35 /* Buildings */ wikitext text/x-wiki == Goal == Get the most victory points at the end of the game. You win some points: * during the game, by acquiring buildings. * at the end of the game, with your civilization cards. == Rules summary == Each round is divided into 3 phases, which are executed in the order described: 1. The players place their people on the game board. 2. The players use the actions of their placed people. 3. The players feed their people. ===Place your people on the game board=== Players placed their people on "rings" (1 people per ring). Special rules with 2 players: * only 1 player in each of the following: forest, clay pit, quarry, and river. * only 2 of the 3 places: tool maker, hut, and field may be filled in each round. Special rules with 3 players: * maximum of 2 players in each of the following: forest, clay pit, quarry, and river. * only 2 of the 3 places: tool maker, hut, and field may be filled in each round. ===Use the actions of your placed people=== Each player uses all his placed people in any order, and realize the corresponding actions: * hunting grounds, forest, clay pit, quarry, and river: roll 1 dice per people and take corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river). * field: increase agriculture level. * tool: get one tool. * hut: get one additional people. * building: buy the building with resources and score points. * civilization card: buy the card with a number of resources depending on its position (1 to 4 resources). ===Resources=== hunting grounds, forest, clay pit, quarry, and river: Roll 1 dice per people and take corresponding resources: * 1 food for each full 2 on hunting grounds, * 1 wood for each full 3 on forest, * 1 brick for each full 4 on clay pit, * 1 stone for each full 5 on quarry, * 1 gold for each full 6 on river. You can use tool to increase the dice result and take more resources. ===Buildings=== Pay the building cost to get the building and receive points. If the building cost is not specified, you win points for each of the resources used, depending on their values (3 for wood, 4 for brick, ...). ===Civilization card details=== Each card brings an immediate advantage (item on the top of the card) and some points during final scoring( item on the bottom of the card). Place the mouse cursor on each card to see details. ===Feed your people=== Each agriculture level automatically give you 1 food. You must use 1 food per person. You can use any resource to feed your people if there is not enough food. If you don't manage to feed your people, you lose 10 points as a penalty. ===Game end=== The game ends when: * there are no more civilization cards at the beginning of a round * one building stack is empty at the end of a round During the final scoring round, players win points using their civilization cards. 6e501537cfc05012c6080c793b3e5560152b5039 97 60 2012-05-18T23:55:17Z Spacediver 718 slight rewrite, according to first learning experience wikitext text/x-wiki == Goal == Get the most victory points at the end of the game. You win some points: * during the game, by acquiring buildings. * at the end of the game, according to civilization cards acquired by you. == Rules summary == Each round is divided into 3 phases, which are executed in the order described: 1. The players place their people on the game board. 2. The players use the actions of their placed people. 3. The players feed their people. ===Place your people on the game board=== Players place groups of their people in places, occupying each "ring" by one people (except for the forest place having no rings). Special rules for game with 2 players only: * no more than 1 player may occupy each of the following places: forest, clay pit, quarry, and river. * no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field Special rules for game with 3 players only: * no more than 2 players may occupy each of the following places: forest, clay pit, quarry, and river. * no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field ===Use the actions of your placed people=== Each player uses all his placed people in any order, and perform the corresponding actions: * '''hunting grounds, forest, clay pit, quarry, and river''': roll 1 dice per people placed and acquire corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river). * '''field''': increase agriculture level. * ''tool maker''': get one tool point (new tool is added, up to 3 in total, after that these tools are upgraded). * '''hut''': get one additional people. * '''building card''': buy the building with resources, scoring some points. * '''civilization card''': buy the card with a number of resources (of any kind) depending on its position (1 to 4 resources depicted above the card). Then the immediate effect of the card is applied. ===Resources=== hunting grounds, forest, clay pit, quarry, and river: Roll 1 dice per people and take corresponding resources: * 1 food for each full 2 on hunting grounds, * 1 wood for each full 3 on forest, * 1 brick for each full 4 on clay pit, * 1 stone for each full 5 on quarry, * 1 gold for each full 6 on river. You may use tools to increase the dice result and take more resources. ===Buildings=== Pay the building cost to get the building and receive points. If the building cost is not fixed (question mark in the corner of the card), you win points for each of the resources used to acquire this building, depending on their values (3 for each wood, 4 for each brick, ...). ===Civilization card details=== Each card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card). Place the mouse cursor on each card to see details in the tooltip. Note that at the list of your acuired civilization cards you will see only the bottom half of each card, for that top half is not relevant anymore. ===Feed your people=== Each agriculture level automatically give you 1 food. You must provide 1 food per person. You may use any resource to feed your people if there is not enough food. If you don't manage to feed your people by means above, you lose 10 points as a penalty. ===Game end=== The game ends when: * there are no more civilization cards at the beginning of a round * one building stack is empty at the end of a round Final number of points for each player is summed out of * points earned during the game by acquiring buildings, minus food penalties, * multipliers denoted at the bottom halfs of civilization cards collected (like number of different culture cards, number of people, tool level etc). 97b0aa912d4b9b69c2f7376b22be6e9e7072bcb4 98 97 2012-05-18T23:56:20Z Spacediver 718 /* Use the actions of your placed people */ wikitext text/x-wiki == Goal == Get the most victory points at the end of the game. You win some points: * during the game, by acquiring buildings. * at the end of the game, according to civilization cards acquired by you. == Rules summary == Each round is divided into 3 phases, which are executed in the order described: 1. The players place their people on the game board. 2. The players use the actions of their placed people. 3. The players feed their people. ===Place your people on the game board=== Players place groups of their people in places, occupying each "ring" by one people (except for the forest place having no rings). Special rules for game with 2 players only: * no more than 1 player may occupy each of the following places: forest, clay pit, quarry, and river. * no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field Special rules for game with 3 players only: * no more than 2 players may occupy each of the following places: forest, clay pit, quarry, and river. * no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field ===Use the actions of your placed people=== Each player uses all his placed people in any order, and perform the corresponding actions: * '''hunting grounds, forest, clay pit, quarry, and river''': roll 1 dice per people placed and acquire corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river). * '''field''': increase agriculture level. * '''tool maker''': get one tool point (new tool is added, up to 3 in total, after that these tools are upgraded). * '''hut''': get one additional people. * '''building card''': buy the building with resources, scoring some points. * '''civilization card''': buy the card with a number of resources (of any kind) depending on its position (1 to 4 resources depicted above the card). Then the immediate effect of the card is applied. ===Resources=== hunting grounds, forest, clay pit, quarry, and river: Roll 1 dice per people and take corresponding resources: * 1 food for each full 2 on hunting grounds, * 1 wood for each full 3 on forest, * 1 brick for each full 4 on clay pit, * 1 stone for each full 5 on quarry, * 1 gold for each full 6 on river. You may use tools to increase the dice result and take more resources. ===Buildings=== Pay the building cost to get the building and receive points. If the building cost is not fixed (question mark in the corner of the card), you win points for each of the resources used to acquire this building, depending on their values (3 for each wood, 4 for each brick, ...). ===Civilization card details=== Each card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card). Place the mouse cursor on each card to see details in the tooltip. Note that at the list of your acuired civilization cards you will see only the bottom half of each card, for that top half is not relevant anymore. ===Feed your people=== Each agriculture level automatically give you 1 food. You must provide 1 food per person. You may use any resource to feed your people if there is not enough food. If you don't manage to feed your people by means above, you lose 10 points as a penalty. ===Game end=== The game ends when: * there are no more civilization cards at the beginning of a round * one building stack is empty at the end of a round Final number of points for each player is summed out of * points earned during the game by acquiring buildings, minus food penalties, * multipliers denoted at the bottom halfs of civilization cards collected (like number of different culture cards, number of people, tool level etc). 287ea7fa1fd741d4cd21c7b7acc067293f636bc6 Contact us 0 9 61 21 2012-01-28T04:56:06Z Azraeldeadlight 63 /* E-mail contact */ wikitext text/x-wiki '''Board Game Arena''' is located in France. == E-mail contact == contact(at)boardgamearena.com We receive *a lot* of e-mails. Please do not send us an e-mail if: * ... you want to report a bug, please do it in the corresponding forum. * ... you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile == Responsible == G. Isabelli 19 bd république 92 260 Fontenay-aux-Roses FRANCE +33 6 17 25 80 34 b19d027459acac0ecff2c30a0bf71a353da4d5e0 Help 0 4 62 13 2012-01-28T04:56:47Z Azraeldeadlight 63 /* Detailed help */ wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena]] ** [[About us]] ** [[Club Board Game Arena]] ** [[Contact us]] === Detailed help === * [[Getting started]] * [[Referral]] * [[Browser support]] * [[Moderation and grades]] * [[Game clock]] * [[Rating]] * [[Reputation]] * [[Translation guidelines]] c6067b5fc3f21568031e1b54885fd097134d4f1d 77 62 2012-03-01T16:30:05Z Yserbius123 229 Added list of games wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena]] ** [[About us]] ** [[Club Board Game Arena]] ** [[Contact us]] === Detailed help === * [[Getting started]] * [[Referral]] * [[Browser support]] * [[Moderation and grades]] * [[Game clock]] * [[Rating]] * [[Reputation]] * [[Translation guidelines]] == Games == * [[Gamehelphaggis|Haggis]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelpdominion|Dominion]] * [[Gamehelpyearofthedragon|In the Year of the Dragon]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelptroyes|Troyes]] * [[Gamehelpgosu|Gosu]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelpamyitis|Amyitis]] * [[Gamehelptobago|Tobago]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpunclechesnutstablegype|Uncle Chesnut's Table Gype]] 7d07756ae02893aca53910e7f887b90075704c79 Faq 0 3 64 24 2012-02-02T00:26:04Z Sunrise 21 /* What is forbidden on Board Game Arena? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamlist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple account and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had a bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. 30db44a0c18a4716b60b3f10ceeebfaab2fd2f29 74 64 2012-02-21T23:26:39Z Sunrise 21 /* Meeting players and starting games */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamlist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: When you win a 2 players game: 1 point. When you win a 3 players game: 1.5 points. When you win a 4 players game: 2 points. etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple account and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had a bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. abd36ffcfe6194a01564f66ee1d74aadb48ddd82 75 74 2012-02-21T23:27:11Z Sunrise 21 /* Meeting players and starting games */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamlist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the table, most of the time it's because there is not yet enough players around the table for playing this game. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple account and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had a bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. edeaf919c942259f6571aeb8fcdae43a6f0ce9e4 Gamehelpdominion 0 29 65 2012-02-02T00:54:39Z Sunrise 21 Created page with "'''Goal''' Be the player with the most victory points at the end of the game. '''Ending Condition''' The ''Province'' stack being depleted, or 3 stacks of cards being deplete..." wikitext text/x-wiki '''Goal''' Be the player with the most victory points at the end of the game. '''Ending Condition''' The ''Province'' stack being depleted, or 3 stacks of cards being depleted. '''Setup''' Each player starts the game with a deck of 10 cards (3 ''Estates'', and 7 ''Copper''). The deck is shuffled and 5 cards are drawn to form the player's hand. '''Overview''' The A-B-C rule makes it easy to remember the play order. On a player's turn: A: Action The player may play an action card. Each player is allowed 1 action per turn by default. Certain action cards provide additional actions. B: Buy After the action phase is over, the player may play buy a card from the general supply. Bought cards are placed in the player's discard pile. Each player is allowed 1 buy per turn by default. Certain action cards provide additional buys. C: Cleanup After the buy phase is over, the player places all cards (played cards and in hand cards) into the discard pile. Five new cards are drawn from the player's deck. If there aren't enough cards to form a full hand, the discard pile is reshuffled and forms the new deck. The game progresses in clockwise order until ending conditions are met. '''Tie-breaker''' If 2 or more players have the same number of victory points, the player that had the fewest number of turns wins. If these is still a tie, all tied players rejoice in a shared victory. 805fe71c99ac402dc86dcc9baf048905fac8d1a2 71 65 2012-02-18T20:50:29Z Camaroman 213 wikitext text/x-wiki '''Goal''' Be the player with the most victory points at the end of the game. '''Ending Condition''' The ''Province'' stack being depleted, or 3 stacks of cards being depleted. '''Setup''' Each player starts the game with a deck of 10 cards (3 ''Estates'', and 7 ''Copper''). The deck is shuffled and 5 cards are drawn to form the player's hand. '''Overview''' The A-B-C rule makes it easy to remember the play order. On a player's turn: A: Action The player may play an action card. Each player is allowed 1 action per turn by default. Certain action cards provide additional actions. B: Buy After the action phase is over, the player may play buy a card from the general supply. Bought cards are placed in the player's discard pile. Each player is allowed 1 buy per turn by default. Certain action cards provide additional buys. C: Cleanup After the buy phase is over, the player places all cards (played cards and in hand cards) into the discard pile. Five new cards are drawn from the player's deck. If there aren't enough cards to form a full hand, the discard pile is reshuffled and forms the new deck. The game progresses in clockwise order until ending conditions are met. '''Tie-breaker''' If 2 or more players have the same number of victory points, the player that had the fewest number of turns wins. If there is still a tie, all tied players rejoice in a shared victory. bc9f64e7b84f58a37339e487710ed67e3593ba84 76 71 2012-02-26T01:36:51Z Dclaw25 248 wikitext text/x-wiki '''Goal''' Be the player with the most victory points at the end of the game. '''Ending Condition''' The ''Province'' stack being depleted, or 3 stacks of cards being depleted. '''Setup''' Each player starts the game with a deck of 10 cards (3 ''Estates'', and 7 ''Copper''). The deck is shuffled and 5 cards are drawn to form the player's hand. '''Overview''' The A-B-C rule makes it easy to remember the play order. On a player's turn: A: Action: The player may play an action card. Each player is allowed 1 action per turn by default. Certain action cards provide additional actions. B: Buy: After the action phase is over, the player may play buy a card from the general supply. Bought cards are placed in the player's discard pile. Each player is allowed 1 buy per turn by default. Certain action cards provide additional buys. C: Cleanup: After the buy phase is over, the player places all cards (played cards and in hand cards) into the discard pile. Five new cards are drawn from the player's deck. If there aren't enough cards to form a full hand, the discard pile is reshuffled and forms the new deck. The game progresses in clockwise order until ending conditions are met. '''Tie-breaker''' If 2 or more players have the same number of victory points, the player that had the fewest number of turns wins. If there is still a tie, all tied players rejoice in a shared victory. 98e728c742c8883c076384792bd60f9fb34bc840 Browser support 0 13 69 36 2012-02-07T08:43:53Z Laszlosaurus 116 emphasized recommended browsers and provided download links wikitext text/x-wiki [[Category:Help]] <h3>For the best experience, we recommend:</h3> * '''Google Chrome 10+''' [http://www.google.com/chrome Windows] [http://www.google.com/chrome?platform=mac Mac] [http://www.google.com/chrome?platform=linux Linux] * '''Mozilla Firefox 4+''' [http://www.mozilla.org/products/firefox/ Windows] [http://www.mozilla.org/products/firefox/ Mac] [http://www.mozilla.org/products/firefox/ Linux] Board Game Arena takes advantage of the most recent web technology to make it possible for you to play without installing anything on your computer: no software to download or update, no plugins to install, etc. Consequently, to play you need to use a modern web browser. Generally speaking, the more recent your web browser is, the more pleasant your game experience on Board Game Arena will be. This website makes intensive use of Javascript and your browser's graphics capabilities. Thus, if you want to have the best gaming experience with Board Game Arena, you should use one of the browsers listed above. However, we officially support the following browsers: * Google Chrome 4+ * Mozilla Firefox 3.5+ * Internet Explorer 9 * Internet Explorer 8 (partial support for IE7) * Safari 4+ (Note: We do NOT support play on iPads or similar tablets.) 3872e0f01d029cea980494755aa10bf990d93e78 Grade 0 30 70 2012-02-09T01:48:50Z Cthulpiss 110 Created page with "Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit o..." wikitext text/x-wiki Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. == All grades == * '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraph can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherub check that Seraph are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...) * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. 71f29ae0ffe6a00b8e4a457aacd391fde8cee61d Rating 0 16 72 38 2012-02-20T05:32:55Z Amagila 220 wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game. == How is my ELO ranking computed ? == The BGA ELO system is inspired by the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. Let's try to make it simple: the points you win/lose after each game depends on the ranking of your opponents. If you win at a table with opponents stronger than you, your ranking will increase a lot. If you lose at the same table, your ranking will decrease a little. And so on ... In case there are more than 2 players at the table, we take into account the final rank. This is the reason it is important to continue fighting for the second place during the game if you think you can't win. == Okay, but I want to know the formula ! == At first, when someone left a game for any reason this game is not taken into account by the ELO rating system. * Table Level (TL) is the average of ELO ratings of all players at this table. * The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player). * The performance (P) of a player is TL+S. * The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO c3ec166f7f82b32d6e93d7108888b93f71461a40 Reputation 0 17 73 40 2012-02-20T05:34:23Z Amagila 220 wikitext text/x-wiki [[Category:Help]] == What is reputation ? == On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance. To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items: * Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png) * % of games you finished * % of games you finished with no clock penalties Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits. == How to increase my reputation / what makes my reputation decrease ? == At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks. * a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player. * a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player. You can only give a single thumb (green or red) to a single player. If your opinion evolved you can click again on a thumb to reflect this change. As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended to leave the game or to expel this player. By nature, opinions are subjectives. There is nothing we can do for you if you receive a for an unfair reason. However, we know by experience that this system has a lot of advantages and give a relevant information. == Advices: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png == * Be polite ! Say at least "hello" and "good luck" at the beginning of the game. "good game" ("gg") at the end of the game. * When you need some time to think, click on "I would like to think a little" link. * Stay calm in any circumstances: it's a game. * Don't press your opponent to play if he has some time left. * If you really can't finish the game (this is not supposed to happened...), then say you are sorry and leave the game by your own to save your opponents time. * Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!). * Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation. == What are the consequences of a bad reputation ? == A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you. It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents. 82e240a99d58813f6fa5c065f5d6a831f89af9d4 Gamehelpdragonheart 0 31 78 2012-03-02T15:38:38Z Yserbius123 229 New page wikitext text/x-wiki ==Summary== Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down. ==Goal== To have the most points by the end of the game. ==Game Start== At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board. ==End== The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 2 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game. ==Turns== Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship. ==Cards== There are five types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it it. Arrows on the board indicate what cards can take what. * ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf. * ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board. * ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards. * ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress. * ''Troll'': Placing this card allows the player to take the sorceress pile. * ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board. * ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent. * ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon. * ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the deck. The ship cards are then discarded. The third time that three ship cards were played ends the game. * ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus two extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand. daaa8873bc1834aa5742568b1a229c985f2a521d 95 78 2012-04-23T19:30:36Z Sourisdudesert 1 wikitext text/x-wiki ==Summary== Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down. ==Goal== To have the most points by the end of the game. ==Game Start== At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board. ==End== The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 2 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game. ==Turns== Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship. ==Cards== There are five types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it it. Arrows on the board indicate what cards can take what. * ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf. * ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board. * ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards. * ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress. * ''Troll'': Placing this card allows the player to take the sorceress pile. * ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board. * ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent. * ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon. * ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the deck. The ship cards are then discarded. The third time that three ship cards were played ends the game. * ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand. a6a9718046f5d9072f2785309784178d640abc81 96 95 2012-04-30T20:53:02Z Christopheryoder 621 /* Cards */ wikitext text/x-wiki ==Summary== Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down. ==Goal== To have the most points by the end of the game. ==Game Start== At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board. ==End== The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 2 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game. ==Turns== Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship. ==Cards== There are five types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it is. Arrows on the board indicate what cards can take what. * ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf. * ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board. * ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards. * ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress. * ''Troll'': Placing this card allows the player to take the sorceress pile. * ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board. * ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent. * ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon. * ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the deck. The ship cards are then discarded. The third time that three ship cards were played ends the game. * ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand. a9e72a95fb991b06d79eaf44b61835a529800b60 Gamehelpsaboteur 0 32 82 2012-03-11T18:05:12Z Een 3 Created page with " == Goal == Get as many gold nuggets as possible during the three rounds of the game. In order to do so, # if you are a '''gold digger''', you must, in association with othe..." wikitext text/x-wiki == Goal == Get as many gold nuggets as possible during the three rounds of the game. In order to do so, # if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards # if you are a '''saboteur''', you must, in association with other gold diggers, prevent the gold diggers to get to the treasure. Your role (gold digger or saboteur) will be randomly selected at the start of each round. == Rules summary == On your turn, you must click on a card from your hand to select it, then play this card or discard it. You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card. The cards are of several types: * 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card. * 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score). * 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you. * 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about. * 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove. == Cards in play == * 44 'Path' cards * 9 'Sabotage' cards (three for each tool) * 6 'Repair a tool' cards (two for each tool) * 3 'Repair a tool among these two' cards (one for each combination of two tools) * 5 'Map' cards (one less than in the box set, as requested by the game author) * 3 'Rock fall' cards * 28 'Gold' cards ** 16 with one gold nugget ** 8 with two gold nuggets ** 4 with three gold nuggets == Roles == Roles are randomly selected among a set that depends upon the number of players: * with 3 players: 1 saboteur and 3 gold diggers * with 4 players: 1 saboteur and 4 gold diggers * with 5 players: 2 saboteurs and 4 gold diggers * with 6 players: 2 saboteurs and 5 gold diggers * with 7 players: 3 saboteurs and 5 gold diggers * with 8 players: 3 saboteurs and 6 gold diggers * with 9 players: 3 saboteurs and 7 gold diggers * with 10 players: 4 saboteurs and 7 gold diggers == Available variants == The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum! '''Have a good game !''' a4923cb01ed4c3387797dd7d0f2a746908e8ed39 83 82 2012-03-11T18:31:04Z Een 3 /* Available variants */ wikitext text/x-wiki == Goal == Get as many gold nuggets as possible during the three rounds of the game. In order to do so, # if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards # if you are a '''saboteur''', you must, in association with other gold diggers, prevent the gold diggers to get to the treasure. Your role (gold digger or saboteur) will be randomly selected at the start of each round. == Rules summary == On your turn, you must click on a card from your hand to select it, then play this card or discard it. You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card. The cards are of several types: * 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card. * 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score). * 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you. * 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about. * 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove. == Cards in play == * 44 'Path' cards * 9 'Sabotage' cards (three for each tool) * 6 'Repair a tool' cards (two for each tool) * 3 'Repair a tool among these two' cards (one for each combination of two tools) * 5 'Map' cards (one less than in the box set, as requested by the game author) * 3 'Rock fall' cards * 28 'Gold' cards ** 16 with one gold nugget ** 8 with two gold nuggets ** 4 with three gold nuggets == Roles == Roles are randomly selected among a set that depends upon the number of players: * with 3 players: 1 saboteur and 3 gold diggers * with 4 players: 1 saboteur and 4 gold diggers * with 5 players: 2 saboteurs and 4 gold diggers * with 6 players: 2 saboteurs and 5 gold diggers * with 7 players: 3 saboteurs and 5 gold diggers * with 8 players: 3 saboteurs and 6 gold diggers * with 9 players: 3 saboteurs and 7 gold diggers * with 10 players: 4 saboteurs and 7 gold diggers == Available variants == The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum! Two variants are about gold sharing: * '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed! * '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!) Two variants are about gameplay: * '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose! * '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded) '''Have a good game !''' 89f9a450f60ec687725cea1fef28dabb34a1dc9b 84 83 2012-03-25T17:25:23Z Coyotek4 143 /* Goal */ wikitext text/x-wiki == Goal == Get as many gold nuggets as possible during the three rounds of the game. In order to do so, # if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards # if you are a '''saboteur''', you must, in association with other saboteurs, prevent the gold diggers to get to the treasure. Your role (gold digger or saboteur) will be randomly selected at the start of each round. == Rules summary == On your turn, you must click on a card from your hand to select it, then play this card or discard it. You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card. The cards are of several types: * 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card. * 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score). * 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you. * 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about. * 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove. == Cards in play == * 44 'Path' cards * 9 'Sabotage' cards (three for each tool) * 6 'Repair a tool' cards (two for each tool) * 3 'Repair a tool among these two' cards (one for each combination of two tools) * 5 'Map' cards (one less than in the box set, as requested by the game author) * 3 'Rock fall' cards * 28 'Gold' cards ** 16 with one gold nugget ** 8 with two gold nuggets ** 4 with three gold nuggets == Roles == Roles are randomly selected among a set that depends upon the number of players: * with 3 players: 1 saboteur and 3 gold diggers * with 4 players: 1 saboteur and 4 gold diggers * with 5 players: 2 saboteurs and 4 gold diggers * with 6 players: 2 saboteurs and 5 gold diggers * with 7 players: 3 saboteurs and 5 gold diggers * with 8 players: 3 saboteurs and 6 gold diggers * with 9 players: 3 saboteurs and 7 gold diggers * with 10 players: 4 saboteurs and 7 gold diggers == Available variants == The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum! Two variants are about gold sharing: * '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed! * '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!) Two variants are about gameplay: * '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose! * '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded) '''Have a good game !''' aa60b7d77920dffe16a09bc974a9b8de56a45063 85 84 2012-03-25T17:26:37Z Coyotek4 143 /* Goal */ wikitext text/x-wiki == Goal == Get as many gold nuggets as possible during the three rounds of the game. In order to do so, # if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards # if you are a '''saboteur''', you must, in association with other saboteurs, prevent the gold diggers from getting to the treasure. Your role (gold digger or saboteur) will be randomly selected at the start of each round. == Rules summary == On your turn, you must click on a card from your hand to select it, then play this card or discard it. You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card. The cards are of several types: * 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card. * 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score). * 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you. * 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about. * 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove. == Cards in play == * 44 'Path' cards * 9 'Sabotage' cards (three for each tool) * 6 'Repair a tool' cards (two for each tool) * 3 'Repair a tool among these two' cards (one for each combination of two tools) * 5 'Map' cards (one less than in the box set, as requested by the game author) * 3 'Rock fall' cards * 28 'Gold' cards ** 16 with one gold nugget ** 8 with two gold nuggets ** 4 with three gold nuggets == Roles == Roles are randomly selected among a set that depends upon the number of players: * with 3 players: 1 saboteur and 3 gold diggers * with 4 players: 1 saboteur and 4 gold diggers * with 5 players: 2 saboteurs and 4 gold diggers * with 6 players: 2 saboteurs and 5 gold diggers * with 7 players: 3 saboteurs and 5 gold diggers * with 8 players: 3 saboteurs and 6 gold diggers * with 9 players: 3 saboteurs and 7 gold diggers * with 10 players: 4 saboteurs and 7 gold diggers == Available variants == The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum! Two variants are about gold sharing: * '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed! * '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!) Two variants are about gameplay: * '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose! * '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded) '''Have a good game !''' ce5786063d5cbea6ae574ca2e25238661377ad54 Gamehelpcoloretto 0 33 86 2012-03-29T15:09:59Z Greywolf 379 Jokers Rule wikitext text/x-wiki In the regular game, one gets to determine where to place the jokers but apparently for this online version, the jokers are auto-allocated to your highest stacks. bb7190f77b09c6cf389d7b52c1a18a36bea5403a Referral 0 11 88 29 2012-04-03T07:31:54Z Toeeatingdog 468 /* How does this work? */ wikitext text/x-wiki [[Category:Help]] When new players discover Board Game Arena thanks to you, you become a member of [[Club Board Game Arena]] == How does this work? == Each time a new player creates an account on Board Game Arena from your referral web address(see below), he becomes one of your '''referees'''. As soon as this referee playes 3 games, you become a member of BGA club. == How to get referees? == To recruit referees, use your personal referrer web address: {sponsorshipurl} New players MUST create an account from this web address to become one of your referees. == How to get many referees? == * [http://boardgamearena.com/#!doc/sponsor?facebook Tell my friends on Facebook] * [http://boardgamearena.com/#!doc/sponsor?twitter Tell my followers on Twitter] * [http://boardgamearena.com/#!doc/sponsor?email Tell my friends by email] * Publish my personal web address in some forum, send it by MSN, ... == How many BGA club membership days can I win? == As soon as your first referee finish his '''third''' game on Board Game Arena, you win a '''1 month''' BGA club membership. ''Note: your account upgrade will be effective within 24 hours.'' As soon as you get '''2 referees''' with at least '''4 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership. As soon as you get '''3 referees''' with at least '''5 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership. ... and so on: as your referees number grows you can win many free memberships ! == Referees and multiple account == It is of course forbidden to create fake referee accounts to win free memberships. 9099f9116dd4534c68393a2381c254cc0c2afa8a 89 88 2012-04-03T07:32:27Z Toeeatingdog 468 /* How does this work? */ wikitext text/x-wiki [[Category:Help]] When new players discover Board Game Arena thanks to you, you become a member of [[Club Board Game Arena]] == How does this work? == Each time a new player creates an account on Board Game Arena from your referrer web address (see below), he becomes one of your '''referees'''. As soon as this referee playes 3 games, you become a member of BGA club. == How to get referees? == To recruit referees, use your personal referrer web address: {sponsorshipurl} New players MUST create an account from this web address to become one of your referees. == How to get many referees? == * [http://boardgamearena.com/#!doc/sponsor?facebook Tell my friends on Facebook] * [http://boardgamearena.com/#!doc/sponsor?twitter Tell my followers on Twitter] * [http://boardgamearena.com/#!doc/sponsor?email Tell my friends by email] * Publish my personal web address in some forum, send it by MSN, ... == How many BGA club membership days can I win? == As soon as your first referee finish his '''third''' game on Board Game Arena, you win a '''1 month''' BGA club membership. ''Note: your account upgrade will be effective within 24 hours.'' As soon as you get '''2 referees''' with at least '''4 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership. As soon as you get '''3 referees''' with at least '''5 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership. ... and so on: as your referees number grows you can win many free memberships ! == Referees and multiple account == It is of course forbidden to create fake referee accounts to win free memberships. 63171eacf8f3dcb07c87ea7f365a438d800754c9 90 89 2012-04-03T07:33:42Z Toeeatingdog 468 /* Referees and multiple account */ wikitext text/x-wiki [[Category:Help]] When new players discover Board Game Arena thanks to you, you become a member of [[Club Board Game Arena]] == How does this work? == Each time a new player creates an account on Board Game Arena from your referrer web address (see below), he becomes one of your '''referees'''. As soon as this referee playes 3 games, you become a member of BGA club. == How to get referees? == To recruit referees, use your personal referrer web address: {sponsorshipurl} New players MUST create an account from this web address to become one of your referees. == How to get many referees? == * [http://boardgamearena.com/#!doc/sponsor?facebook Tell my friends on Facebook] * [http://boardgamearena.com/#!doc/sponsor?twitter Tell my followers on Twitter] * [http://boardgamearena.com/#!doc/sponsor?email Tell my friends by email] * Publish my personal web address in some forum, send it by MSN, ... == How many BGA club membership days can I win? == As soon as your first referee finish his '''third''' game on Board Game Arena, you win a '''1 month''' BGA club membership. ''Note: your account upgrade will be effective within 24 hours.'' As soon as you get '''2 referees''' with at least '''4 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership. As soon as you get '''3 referees''' with at least '''5 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership. ... and so on: as your referees number grows you can win many free memberships ! == Referees and multiple accounts == It is of course forbidden to create fake referee accounts to win free memberships. aae72040c79a6b18ef8bd1486cd56f5f97eb30d7 Gamehelphawaii 0 34 91 2012-04-04T08:57:29Z Tobylongbeach 477 Created page with "Overview: You are the chieftain of a kingdom (your placemat) with up to five villages (rows). You buy or go to the islands to get place tiles that you put in your villages. Th..." wikitext text/x-wiki Overview: You are the chieftain of a kingdom (your placemat) with up to five villages (rows). You buy or go to the islands to get place tiles that you put in your villages. There are five rounds and you get a decreasing amount of resources each round with which to acquire place tiles. Its a many-paths-to-victory kind of game. There are three kinds of resources: 1) Feet - let you move around the board, or travel to the islands or go to the cove to catch fish. 2) Clam shells - let you buy place tiles from the board 3) Fruit - can be used in place of feet or clam shells in all-or-nothing fashion. If you substitute for feet, you must substitute the entire moving cost. If you substitute for clams, you must substitute the entire purchase price. Moving: Your chieftain start at the beach and it costs nothing to return there from the board. Each movement in from the beach costs one foot. Moving up, down, right, left or diagonal on the board costs one foot per space. Staying on a space costs one foot. To go to the islands, you use your boats and feet. The closest island costs three feet and the farthest costs six. You have to have the feet as well as the space on the boats for the feet. You get an immediate victory point bonus for going to the islands but you do not get a price token (more about that later). Also, you get the level 2 version of whatever place tile or item you are getting on the islands. For instance, to go to the six foot island, you would need either: A) two three-feet boats and six feet resources or B) you would need the four-foot boat (which comes with a prepaid foot) and the two-foot boat as well as five feet resources. That is the advantage of the pre-paid foot on the four-foot boat. == Purchasing: == To buy some thing from the board: Select the price token (round colored circle with number inside) on the space with the place tile or item you want. If there is more than one place tile available on that space, you will be given a choice of which one you want. The movement cost will be in feet and the purchase price will be in clam shells but you can substitute either or both with fruit if you have it. You gain the price token for the round. There must be an available price token in order to purchase something from that space. You can pay double to get the level 2 version, which for most tiles is double effect. You place it in the village (row) of your choice. You must be able to place it in order to purchase it. A) You can only have one of each type of place tile in each village. For instance, you cannot have a foot (1) hut and a foot (2) hut in the same village but you can have a coconut fruit (1) tree and a breadfruit (2) tree in the same village. B) You can have only one god in each village. You can only have one of each type of god in your whole kingdom and the god vp effects are kingdom-wide. B) Each village must begin with a hut. The huts have a picture of a hut on them: foot hut, clam hut, spear hut, exchange hut, and long hut. ''' == Resources == ''' == Base reources == Base resources are on the round indicator. They decrease with each succeeding round. Everyone gets the base resources at the beginning of the round. Any unused resources can be used in the next round. == In-play resource bonuses == *The third, fourth and fifth villages give you 1, 2 and 3 clams respectively when you purchase Kahunas (Hawaiian priests) for them. *When you purchase for your kingdom the second, third and fourth Tikis, you are granted 1, 2, and 3 feet, respectively. *One or two of the island treasures are four fruit resources. == Resource Generators: == generate resources at the beginning of the next round. Fruit level ones - one fruit Fruit level twos - two fruit Clam hut level one - one clam Clam hut level two - two clams Foot hut level one - one foot Foot hut level two - two feet Irrigation level two - one resource of your choice Ku god - level one and two - one foot Kane god level one - one clam Kane god level two - two clams '''== Victory Points ==''' == In-play VP's: == *Going to the islands gives you a vp bonus. *Some of the treasures on the islands are 5 vp's. *Spear huts and the Ku god give you a bonus whenever you take a price token with crossed spears. Level 1 is 1 pt. bonus, Level 2 is two pt. bonus. == Round-End VP's: == There is a large sheild on the round indicator at the bottom. If the sum of price tokens and fish are greater than the number on the sheild, then you get a bonus. There is a large bonus for the player with highest sum score, a moderate bonus for the second highest and a token bonus for everyone else whose sum was greater than the sheild. Surfer place tiles lower the sheild value for qualifying for the bonus but surfers do not contribute to your sum when comparing to other players. Lono god level 1 gives you 2 vp's if you qualify for the bonus, and Lono god level 2 gives you 4 vp's if you qualify for the bonus == Game-End VP's: == A) Each village whose size extends to the Tikis and which possesses a Kahuna is active and receives a bonus, listed next to the Kahunas. The first, second, third, fourth and fifth villages receive five, five, ten, ten and fifteen points respectively. Only active villages score points for place tiles in the village. B) Hula dancer gives you one point for each place tile in her village including herself. Level 2 hula dancer gives you two points instead of one. C) Irrigation gives you pts for each type of fruit you have in that particular village. D) Long Hut level 2 is worth five points. E) Laka god scores one pt for each fruit symbol on your place tiles. Laka god level 2 scores two points for each fruit symbol. F) Kanaloa god scores two pts for each boat and surfer. Kanaloa 2 scores 4 pts for each boat and surfer. c7659be503bee1cb94d917358ea72ccc219c822d Gamehelpcantstop 0 35 92 2012-04-16T17:11:49Z Iakwvina 538 Created page with "Can't Stop is a very easy and fast game! '''How to play''' You roll 4 dices and then you decide which summaries of 2 dices you want to use.When you do that,you place the tem..." wikitext text/x-wiki Can't Stop is a very easy and fast game! '''How to play''' You roll 4 dices and then you decide which summaries of 2 dices you want to use.When you do that,you place the temporary markers on the game board.You are allowed to use 3 temporary markers.These markers are commonly white or black.You continue to roll the dices hoping to bring one of the previous combinations.When you think that it is enough you must say "STOP". Then you replace the white markers with yours.If you roll the dices and there is not possible combination you fail and your progress doesn't be saved.The game board has paths from 2 to 12.The most common are 6,7 and 8 so they have more steps in their paths. '''The object of the game is''' to reach and cover 3 peeks of these paths! 1c67b4df40a8303ccc8214a7e52670b1f7e4ffbe 93 92 2012-04-17T00:45:02Z Jleidich 100 wikitext text/x-wiki Can't Stop is a very easy and fast game! '''How to play''' Roll 4 standard dice and then choose the sums of any 2 dice to advance your position on the board. You are allowed to use 3 temporary markers to track your progress in columns marked 2 through 12. These markers are commonly white or black. You can continue to roll the dice hoping to roll one of the previous combinations in the three columns selected this turn. When you think you've pushed your luck far enough you say "STOP" then pass the dice to the next player and replace the white markers with your own. If you roll the dice and find no useful combination you fail and your progress is lost. The more common numbers on 2d6 (6,7 and 8) have more steps in their paths while the less common combinations (2 and 12) have less. '''The object of the game is''' to reach and cover 3 peaks of these columns! a3f0344e922c7148713a1809f6a3e5275412f2f6 Sponsor 0 36 94 2012-04-17T18:31:04Z Een 3 Redirected page to [[Referral]] wikitext text/x-wiki #REDIRECT [[Referral]] ad3d24fb99469ddbdfa9c56714b949f98a1e82b8 Gamehelpstoneage 0 21 99 98 2012-05-18T23:57:16Z Spacediver 718 /* Civilization card details */ wikitext text/x-wiki == Goal == Get the most victory points at the end of the game. You win some points: * during the game, by acquiring buildings. * at the end of the game, according to civilization cards acquired by you. == Rules summary == Each round is divided into 3 phases, which are executed in the order described: 1. The players place their people on the game board. 2. The players use the actions of their placed people. 3. The players feed their people. ===Place your people on the game board=== Players place groups of their people in places, occupying each "ring" by one people (except for the forest place having no rings). Special rules for game with 2 players only: * no more than 1 player may occupy each of the following places: forest, clay pit, quarry, and river. * no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field Special rules for game with 3 players only: * no more than 2 players may occupy each of the following places: forest, clay pit, quarry, and river. * no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field ===Use the actions of your placed people=== Each player uses all his placed people in any order, and perform the corresponding actions: * '''hunting grounds, forest, clay pit, quarry, and river''': roll 1 dice per people placed and acquire corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river). * '''field''': increase agriculture level. * '''tool maker''': get one tool point (new tool is added, up to 3 in total, after that these tools are upgraded). * '''hut''': get one additional people. * '''building card''': buy the building with resources, scoring some points. * '''civilization card''': buy the card with a number of resources (of any kind) depending on its position (1 to 4 resources depicted above the card). Then the immediate effect of the card is applied. ===Resources=== hunting grounds, forest, clay pit, quarry, and river: Roll 1 dice per people and take corresponding resources: * 1 food for each full 2 on hunting grounds, * 1 wood for each full 3 on forest, * 1 brick for each full 4 on clay pit, * 1 stone for each full 5 on quarry, * 1 gold for each full 6 on river. You may use tools to increase the dice result and take more resources. ===Buildings=== Pay the building cost to get the building and receive points. If the building cost is not fixed (question mark in the corner of the card), you win points for each of the resources used to acquire this building, depending on their values (3 for each wood, 4 for each brick, ...). ===Civilization card details=== Each card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card). Place the mouse cursor on each card to see details in the tooltip. Note that at the list of your acquired civilization cards you will see only the bottom half of each card, for that top half is not relevant anymore. ===Feed your people=== Each agriculture level automatically give you 1 food. You must provide 1 food per person. You may use any resource to feed your people if there is not enough food. If you don't manage to feed your people by means above, you lose 10 points as a penalty. ===Game end=== The game ends when: * there are no more civilization cards at the beginning of a round * one building stack is empty at the end of a round Final number of points for each player is summed out of * points earned during the game by acquiring buildings, minus food penalties, * multipliers denoted at the bottom halfs of civilization cards collected (like number of different culture cards, number of people, tool level etc). 8055236dec4e47f0d97b4a11798e1d8683139159 135 99 2012-06-26T15:37:57Z Bastan 978 /* Game end */ wikitext text/x-wiki == Goal == Get the most victory points at the end of the game. You win some points: * during the game, by acquiring buildings. * at the end of the game, according to civilization cards acquired by you. == Rules summary == Each round is divided into 3 phases, which are executed in the order described: 1. The players place their people on the game board. 2. The players use the actions of their placed people. 3. The players feed their people. ===Place your people on the game board=== Players place groups of their people in places, occupying each "ring" by one people (except for the forest place having no rings). Special rules for game with 2 players only: * no more than 1 player may occupy each of the following places: forest, clay pit, quarry, and river. * no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field Special rules for game with 3 players only: * no more than 2 players may occupy each of the following places: forest, clay pit, quarry, and river. * no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field ===Use the actions of your placed people=== Each player uses all his placed people in any order, and perform the corresponding actions: * '''hunting grounds, forest, clay pit, quarry, and river''': roll 1 dice per people placed and acquire corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river). * '''field''': increase agriculture level. * '''tool maker''': get one tool point (new tool is added, up to 3 in total, after that these tools are upgraded). * '''hut''': get one additional people. * '''building card''': buy the building with resources, scoring some points. * '''civilization card''': buy the card with a number of resources (of any kind) depending on its position (1 to 4 resources depicted above the card). Then the immediate effect of the card is applied. ===Resources=== hunting grounds, forest, clay pit, quarry, and river: Roll 1 dice per people and take corresponding resources: * 1 food for each full 2 on hunting grounds, * 1 wood for each full 3 on forest, * 1 brick for each full 4 on clay pit, * 1 stone for each full 5 on quarry, * 1 gold for each full 6 on river. You may use tools to increase the dice result and take more resources. ===Buildings=== Pay the building cost to get the building and receive points. If the building cost is not fixed (question mark in the corner of the card), you win points for each of the resources used to acquire this building, depending on their values (3 for each wood, 4 for each brick, ...). ===Civilization card details=== Each card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card). Place the mouse cursor on each card to see details in the tooltip. Note that at the list of your acquired civilization cards you will see only the bottom half of each card, for that top half is not relevant anymore. ===Feed your people=== Each agriculture level automatically give you 1 food. You must provide 1 food per person. You may use any resource to feed your people if there is not enough food. If you don't manage to feed your people by means above, you lose 10 points as a penalty. ===Game end=== The game ends when: * there are no more civilization cards at the beginning of a round * one building stack is empty at the end of a round Final number of points for each player is summed out of * points earned during the game by acquiring buildings, minus food penalties, * multipliers denoted at the bottom halfs of civilization cards collected (like number of different culture cards, number of people, tool level etc). * each resource that a player has on his player board scores 1 point a253652bd7e7b7a766518baaba762f793c4fe7f6 Faq 0 3 100 75 2012-05-19T00:05:58Z Spacediver 718 /* I joined a game. When does the game start? */ (removed confusion of 'around the table' with 'joined the table') wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamlist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple account and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had a bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. a22edcd73f518e3d5b1421a84dfce0e7bd9832b4 Gamehelphawaii 0 34 101 91 2012-05-20T18:07:54Z Tobylongbeach 477 wikitext text/x-wiki Overview: You are the chieftain of a kingdom (your placemat) with up to five villages (rows). You buy or go to the islands to get place tiles that you put in your villages. There are five rounds and you get a decreasing amount of resources each round with which to acquire place tiles. Its a many-paths-to-victory kind of game. There are three kinds of resources: 1) Feet - let you move around the board, or travel to the islands or go to the cove to catch fish. 2) Clam shells - let you buy place tiles from the board 3) Fruit - can be used in place of feet or clam shells in all-or-nothing fashion. If you substitute for feet, you must substitute the entire moving cost. If you substitute for clams, you must substitute the entire purchase price. Moving: Your chieftain start at the beach and it costs nothing to return there from the board. Each movement in from the beach costs one foot. Moving up, down, right, left or diagonal on the board costs one foot per space. Staying on a space costs one foot. To go to the islands, you use your boats and feet. The closest island costs three feet and the farthest costs six. You have to have the feet as well as the space on the boats for the feet. You get an immediate victory point bonus for going to the islands but you do not get a price token (more about that later). Also, you get the level 2 version of whatever place tile or item you are getting on the islands. For instance, to go to the six foot island, you would need either: A) two three-feet boats and six feet resources or B) you would need the four-foot boat (which comes with a prepaid foot) and the two-foot boat as well as five feet resources. That is the advantage of the pre-paid foot on the four-foot boat. == Purchasing: == To buy some thing from the board: Select the price token (round colored circle with number inside) on the space with the place tile or item you want. If there is more than one place tile available on that space, you will be given a choice of which one you want. The movement cost will be in feet and the purchase price will be in clam shells but you can substitute either or both with fruit if you have it. You gain the price token for the round. There must be an available price token in order to purchase something from that space. You can pay double to get the level 2 version, which for most tiles is double effect. You place it in the village (row) of your choice. You must be able to place it in order to purchase it. A) You can only have one of each type of place tile in each village. For instance, you cannot have a foot (1) hut and a foot (2) hut in the same village but you can have a coconut fruit (1) tree and a breadfruit (2) tree in the same village. B) You can have only one god in each village. You can only have one of each type of god in your whole kingdom and the god vp effects are kingdom-wide. B) Each village must begin with a hut. The huts have a picture of a hut on them: foot hut, clam hut, spear hut, exchange hut, and long hut. ''' == Resources == ''' == Base reources == Base resources are on the round indicator. They decrease with each succeeding round. Everyone gets the base resources at the beginning of the round. Any unused resources can be used in the next round. == In-play resource bonuses == *The third, fourth and fifth villages give you 1, 2 and 3 clams respectively when you purchase Kahunas (Hawaiian priests) for them. *When you purchase for your kingdom the second, third and fourth Tikis, you are granted 1, 2, and 3 feet, respectively. *One or two of the island treasures are four fruit resources. == Resource Generators: == generate resources at the beginning of the next round. *Fruit level ones - one fruit *Fruit level twos - two fruit *Clam hut level one - one clam *Clam hut level two - two clams *Foot hut level one - one foot *Foot hut level two - two feet *Irrigation level two - one resource of your choice *Ku god - level one and two - one foot *Kane god level one - one clam *Kane god level two - two clams '''== Victory Points ==''' == In-play VP's: == *Going to the islands gives you a vp bonus. *Some of the treasures on the islands are 5 vp's. *Spear huts and the Ku god give you a bonus whenever you take a price token with crossed spears. Level 1 is 1 pt. bonus, Level 2 is two pt. bonus. == Round-End VP's: == There is a large sheild on the round indicator at the bottom. If the sum of price tokens and fish are greater than the number on the sheild, then you get a bonus. There is a large bonus for the player with highest sum score, a moderate bonus for the second highest and a token bonus for everyone else whose sum was greater than the sheild. Surfer place tiles lower the sheild value for qualifying for the bonus but surfers do not contribute to your sum when comparing to other players. Lono god level 1 gives you 2 vp's if you qualify for the bonus, and Lono god level 2 gives you 4 vp's if you qualify for the bonus == Game-End VP's: == A) Each village whose size extends to the Tikis and which possesses a Kahuna is active and receives a bonus, listed next to the Kahunas. The first, second, third, fourth and fifth villages receive five, five, ten, ten and fifteen points respectively. Only active villages score points for place tiles in the village. B) Hula dancer gives you one point for each place tile in her village including herself. Level 2 hula dancer gives you two points instead of one. C) Irrigation gives you pts for each type of fruit you have in that particular village. D) Long Hut level 2 is worth five points. E) Laka god scores one pt for each fruit symbol on your place tiles. Laka god level 2 scores two points for each fruit symbol. F) Kanaloa god scores two pts for each boat and surfer. Kanaloa 2 scores 4 pts for each boat and surfer. a5b2616a703904b9170cd5ac89d2fbd3cbbf94d5 Rating 0 16 102 72 2012-05-26T13:50:59Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game ? == ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples: * If you end the game at a better place than a player with a higher ELO, you gain a lot of points. * If you end the game at a better place than a player with a lower ELO, you gain less points. * If you end the game at a worse place than a player with a lower ELO, you loose a lot points. * And so on... == How is my ELO ranking computed ? == The BGA ELO system is inspired by the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. Let's try to make it simple: the points you win/lose after each game depends on the ranking of your opponents. If you win at a table with opponents stronger than you, your ranking will increase a lot. If you lose at the same table, your ranking will decrease a little. And so on ... In case there are more than 2 players at the table, we take into account the final rank. This is the reason it is important to continue fighting for the second place during the game if you think you can't win. == Okay, but I want to know the formula ! == At first, when someone left a game for any reason this game is not taken into account by the ELO rating system. * Table Level (TL) is the average of ELO ratings of all players at this table. * The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player). * The performance (P) of a player is TL+S. * The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO a6dc048df01d400d3a40159030d500d2c6d0eeb7 103 102 2012-05-26T14:00:10Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game ? == ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples: * If you end the game at a better place than a player with a higher ELO, you gain a lot of points. * If you end the game at a better place than a player with a lower ELO, you gain less points. * If you end the game at a worse place than a player with a lower ELO, you loose a lot points. * And so on... == Some advice == * There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO. * The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you loose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent. == How is my ELO ranking computed ? == The BGA ELO system is inspired by the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. Let's try to make it simple: the points you win/lose after each game depends on the ranking of your opponents. If you win at a table with opponents stronger than you, your ranking will increase a lot. If you lose at the same table, your ranking will decrease a little. And so on ... In case there are more than 2 players at the table, we take into account the final rank. This is the reason it is important to continue fighting for the second place during the game if you think you can't win. == Okay, but I want to know the formula ! == At first, when someone left a game for any reason this game is not taken into account by the ELO rating system. * Table Level (TL) is the average of ELO ratings of all players at this table. * The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player). * The performance (P) of a player is TL+S. * The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO 35a2f8521b67c643b02c1cfed37ce9bd61ac058e 104 103 2012-05-26T14:04:17Z Sourisdudesert 1 /* How is my ELO ranking computed ? */ wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game ? == ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples: * If you end the game at a better place than a player with a higher ELO, you gain a lot of points. * If you end the game at a better place than a player with a lower ELO, you gain less points. * If you end the game at a worse place than a player with a lower ELO, you loose a lot points. * And so on... == Some advice == * There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO. * The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you loose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent. == How is my ELO ranking computed ? == The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied. == Okay, but I want to know the formula ! == At first, when someone left a game for any reason this game is not taken into account by the ELO rating system. * Table Level (TL) is the average of ELO ratings of all players at this table. * The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player). * The performance (P) of a player is TL+S. * The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO e52ee9312119ec37ea571332e9f96cf44c69833b 105 104 2012-05-26T14:04:53Z Sourisdudesert 1 /* Some advice */ wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game ? == ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples: * If you end the game at a better place than a player with a higher ELO, you gain a lot of points. * If you end the game at a better place than a player with a lower ELO, you gain less points. * If you end the game at a worse place than a player with a lower ELO, you loose a lot points. * And so on... == Some advice == * There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO. * The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win. * The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you loose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent. == How is my ELO ranking computed ? == The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied. == Okay, but I want to know the formula ! == At first, when someone left a game for any reason this game is not taken into account by the ELO rating system. * Table Level (TL) is the average of ELO ratings of all players at this table. * The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player). * The performance (P) of a player is TL+S. * The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO e7710d254d0b0589ff5ca25ac485b8c6f3a44bbf 106 105 2012-05-26T14:15:09Z Sourisdudesert 1 /* How is my ELO ranking computed ? */ wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game ? == ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples: * If you end the game at a better place than a player with a higher ELO, you gain a lot of points. * If you end the game at a better place than a player with a lower ELO, you gain less points. * If you end the game at a worse place than a player with a lower ELO, you loose a lot points. * And so on... == Some advice == * There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO. * The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win. * The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you loose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent. == How is my ELO ranking computed ? == The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied. ELO system on BGA has some specificity: * During your first 30 games, your ELO rating is more "elastic": you can win (or loose) more points at each game. This way, your ELO rating converge faster to you "natural" rating. * Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you loose a 2-player game against each opponent before you (in game rank). * Games with more than 2 players last longer. For this reason, there's more points to win (or loose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula ! == At first, when someone left a game for any reason this game is not taken into account by the ELO rating system. * Table Level (TL) is the average of ELO ratings of all players at this table. * The success (S) of a player depends directly on its ranking at the game, from S=+470 (winner of the game) to S=-470 (last player). * The performance (P) of a player is TL+S. * The new ELO rating (Rn) is a weighted average of the previous ELO rating (Rp) and the performance: Rn = K.P + (1-K).Rp == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO 3cd935f80c6c6f00744f005218d18d42bd5e6acf 107 106 2012-05-26T14:18:41Z Sourisdudesert 1 /* Okay, but I want to know the formula ! */ wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game ? == ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples: * If you end the game at a better place than a player with a higher ELO, you gain a lot of points. * If you end the game at a better place than a player with a lower ELO, you gain less points. * If you end the game at a worse place than a player with a lower ELO, you loose a lot points. * And so on... == Some advice == * There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO. * The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win. * The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you loose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent. == How is my ELO ranking computed ? == The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied. ELO system on BGA has some specificity: * During your first 30 games, your ELO rating is more "elastic": you can win (or loose) more points at each game. This way, your ELO rating converge faster to you "natural" rating. * Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you loose a 2-player game against each opponent before you (in game rank). * Games with more than 2 players last longer. For this reason, there's more points to win (or loose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula ! == The formula is exactly one's used by the ELO rating system, with the following adjustments: * At first, when someone left a game for any reason this game is not taken into account by the ELO rating system. * K=60 for the first 30 games, K=40 afterwards. * K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players". * If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600. == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO 83d9c1282c8bbed7224adc1193fa6025698360b1 Gamehelpcaylus 0 37 108 2012-06-08T12:16:00Z Xeno611 648 a fix wikitext text/x-wiki The link above for the rules text is broken, here is the proper one [http://www.ystari.com/caylus/CayUS.pdf Caylus Rule book] dec8842e16c43a0bdf8306d09cefef9977201436 Gamehelpdiams 0 38 109 2012-06-13T20:56:30Z Een 3 Created page with " == Goal == Get as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color or more (up to five). Each color has a matchi..." wikitext text/x-wiki == Goal == Get as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color or more (up to five). Each color has a matching value between 1 to 10. == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market Then you will have to choose between two actions (phase 2): * Select one of your card and go to the market with this card. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose values sum up to the value of the card you went to the market with ** Come back empty ended * Select cards in your hand and secure them into your safe. Your selection: ** Must contain at least one collection ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some cards to keep only 5. == Special cards == == Available variants == '''Have a good game !''' c548022931a8d0df231a0d4b6e840d226e525204 110 109 2012-06-13T21:06:55Z Een 3 wikitext text/x-wiki == Goal == Secure as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. On each round, you'll earn victory chips based on the points earned collecting diamonds. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is the '7', not the '10') The player with the most victory chips at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two actions (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. Your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == == Available variants == '''Have a good game !''' ceb5509a22f4538c3055f3866cc8ebb9dbac81f4 111 110 2012-06-13T21:21:17Z Een 3 /* Available variants */ wikitext text/x-wiki == Goal == Secure as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. On each round, you'll earn victory chips based on the points earned collecting diamonds. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is the '7', not the '10') The player with the most victory chips at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two actions (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. Your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game !''' 643d9f4bc5d615656496eb5a5ed70d66cf6da703 112 111 2012-06-13T21:31:05Z Een 3 /* Special cards */ wikitext text/x-wiki == Goal == Secure as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. On each round, you'll earn victory chips based on the points earned collecting diamonds. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is the '7', not the '10') The player with the most victory chips at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two actions (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. Your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market ''Secur`express'' enables you to secure diamonds of one quality already present in your safe ''Safe drilling'' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent ''Sleight of hand'' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game !''' d596468bbd4851645c67eb9a7a0cb676984c0ec6 113 112 2012-06-13T21:32:39Z Een 3 /* Goal */ wikitext text/x-wiki == Goal == Secure as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10') On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two actions (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. Your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market ''Secur`express'' enables you to secure diamonds of one quality already present in your safe ''Safe drilling'' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent ''Sleight of hand'' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game !''' 43e2f2bf0e3fbfaa319218cfe03ee62cef32271a 114 113 2012-06-13T21:34:02Z Een 3 /* Rules summary */ wikitext text/x-wiki == Goal == Secure as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10') On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two actions (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market ''Secur`express'' enables you to secure diamonds of one quality already present in your safe ''Safe drilling'' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent ''Sleight of hand'' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game !''' 695fba417b313f914ffd6c149492f05049def263 115 114 2012-06-13T21:34:25Z Een 3 /* Special cards */ wikitext text/x-wiki == Goal == Secure as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10') On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two actions (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game !''' 19ceabc9061b0a187671c4db40e214f66516dc65 116 115 2012-06-13T21:34:42Z Een 3 /* Available variants */ wikitext text/x-wiki == Goal == Secure as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10') On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two actions (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game !''' 6131f77032d5baa37874120100912d9bdb56cf75 117 116 2012-06-13T21:37:38Z Een 3 /* Goal */ wikitext text/x-wiki == Goal == Secure as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity in his safe (magnifying glass symbol) and for the player whose diamonds digits in hand sum up to the biggest value. On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two actions (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game !''' d1b0220c82a08620127520971f823abe8813b2b2 118 117 2012-06-13T21:39:26Z Een 3 /* Goal */ wikitext text/x-wiki == Goal == Secure as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity in his safe (magnifying glass symbol, 5 bonus points, 2 points in case of a tie) and for the player whose diamonds digits in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two actions (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game !''' 868fbcf9a41ea50e24a1a14474160cce69b6733b 119 118 2012-06-13T21:40:34Z Een 3 /* Goal */ wikitext text/x-wiki == Goal == Secure as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two actions (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other and unique power. Available powers are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game !''' 6e0a67b750f9a539b72ac427ef89189b58fd6016 120 119 2012-06-13T21:41:33Z Een 3 /* Special cards */ wikitext text/x-wiki == Goal == Secure as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two actions (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity straight from the safe of an opponent '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game !''' e04a679791f79449ec50aa30c74413cf1e5df788 121 120 2012-06-13T21:42:01Z Een 3 /* Special cards */ wikitext text/x-wiki == Goal == Secure as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds. The player with the most victory chips at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two actions (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game !''' 5ac6a2422de77758d42de4dc6cb285e50c1d730e 122 121 2012-06-13T21:45:22Z Een 3 /* Goal */ wikitext text/x-wiki == Goal == Secure as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 and so on). The player with the most victory chips at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two actions (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game !''' e8f0cd0e229a5b47857ebd7b85a02ae1fabc94d4 123 122 2012-06-13T21:45:39Z Een 3 /* Goal */ wikitext text/x-wiki == Goal == Secure as many diamond collections as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the most victory chips at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two actions (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game !''' 9cfe856cf374159dc625af28fbb99068cc5d0266 124 123 2012-06-13T21:46:29Z Een 3 /* Goal */ wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two possibilities (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two actions (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game !''' 1f43bf7cba2bf5a15119b37f4e4ca3b63e58f395 125 124 2012-06-13T21:47:30Z Een 3 /* Rules summary */ wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two 'draw actions' (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two 'play actions' (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game !''' 8dbb958af624cfa3ddb5963303e0f8fbfc902997 126 125 2012-06-15T18:53:45Z Een 3 wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two 'draw actions' (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two 'play actions' (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game!''' 92496c4b6e26fb4f7c997524ee11bcbd1fdf9cd6 127 126 2012-06-15T18:56:45Z Een 3 wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round : * for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) * and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! == Rules summary == On your turn, you must first choose between two 'draw actions' (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two 'play actions' (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!) '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game!''' 39b1f29563cdb81647bdd16d15da8b20442a7718 128 127 2012-06-16T13:46:46Z Een 3 wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round : * for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) * and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory) == Rules summary == On your turn, you must first choose between two 'draw actions' (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two 'play actions' (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!) '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game!''' 8da68d505b4bab957ec3a8b0c562e040f7ced9dc 129 128 2012-06-18T18:49:28Z Een 3 /* Goal */ wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching quality digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round : * for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) * and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory) == Rules summary == On your turn, you must first choose between two 'draw actions' (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two 'play actions' (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!) '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality, or a diamond of exceptional purity, straight from the safe of an opponent '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game!''' 7f051d4fe265413fd7537709dbadfe420396ed1f 130 129 2012-06-18T18:51:57Z Een 3 /* Special cards */ wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching quality digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round : * for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) * and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory) == Rules summary == On your turn, you must first choose between two 'draw actions' (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two 'play actions' (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!) '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (please take note however, if your opponent doesn't have any diamond of this kind, drilling will fail!) '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game!''' 45da0f7bedaf3c9f89202f20840a6bd2d54e5c65 131 130 2012-06-18T18:59:23Z Een 3 /* Goal */ wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round : * for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) * and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory) == Rules summary == On your turn, you must first choose between two 'draw actions' (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two 'play actions' (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!) '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (please take note however, if your opponent doesn't have any diamond of this kind, drilling will fail!) '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game!''' 43ea17ba2484b5535f8073731b3d0c7a6eeafffd 132 131 2012-06-18T18:59:56Z Een 3 /* Special cards */ wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round : * for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) * and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory) == Rules summary == On your turn, you must first choose between two 'draw actions' (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two 'play actions' (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!) '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (please take note however that if your opponent doesn't have any diamond of this kind, drilling will fail!) '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game!''' 11ee17814253934e13773d95ad05fd1a98616ea9 133 132 2012-06-18T19:00:33Z Een 3 /* Special cards */ wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round : * for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) * and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory) == Rules summary == On your turn, you must first choose between two 'draw actions' (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two 'play actions' (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!) '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (of course, if your opponent doesn't have any diamond of this kind, drilling will fail!) '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game!''' f7ae2b1fd802f3d68b779ddba760461388c132dd 134 133 2012-06-18T19:47:14Z Een 3 /* Special cards */ wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round : * for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) * and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory) == Rules summary == On your turn, you must first choose between two 'draw actions' (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two 'play actions' (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power you to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!) '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (but of course, if your opponent doesn't have any diamond of this kind, drilling will fail!) '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game!''' 9a4d8f6b6f72f40fca58395367ce2b205dfd0e11 Contact us 0 9 136 61 2012-06-27T18:25:25Z Een 3 wikitext text/x-wiki '''Board Game Arena''' is located in France. == Contact e-mail == contact(at)boardgamearena.com We receive ''a lot'' of e-mails. Please do not send us an e-mail in any of these two cases: * If you want to report a bug, please do it in the corresponding forum * If you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile. == Responsible == G. Isabelli 19 bd république 92 260 Fontenay-aux-Roses FRANCE +33 6 17 25 80 34 51933312a01a4748b0ec1631205b3a80418dc06d 137 136 2012-06-27T18:29:32Z Een 3 /* Contact e-mail */ wikitext text/x-wiki '''Board Game Arena''' is located in France. == Contact e-mail == contact(at)boardgamearena.com We receive '''a lot''' of e-mails. Please do not send us an e-mail in any of these two cases: * If you want to report a bug, please do it in the corresponding forum * If you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile. == Responsible == G. Isabelli 19 bd république 92 260 Fontenay-aux-Roses FRANCE +33 6 17 25 80 34 7bf5a90e4b8f025c1ae505fd06cd2eff3a1e50d2 138 137 2012-06-27T18:29:51Z Een 3 /* Responsible */ wikitext text/x-wiki '''Board Game Arena''' is located in France. == Contact e-mail == contact(at)boardgamearena.com We receive '''a lot''' of e-mails. Please do not send us an e-mail in any of these two cases: * If you want to report a bug, please do it in the corresponding forum * If you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile. == Administrator == G. Isabelli 19 bd république 92 260 Fontenay-aux-Roses FRANCE +33 6 17 25 80 34 62315f21725bfc9363f06b56eb43a553eb505eb1 139 138 2012-06-27T18:31:18Z Een 3 /* Administrator */ wikitext text/x-wiki '''Board Game Arena''' is located in France. == Contact e-mail == contact(at)boardgamearena.com We receive '''a lot''' of e-mails. Please do not send us an e-mail in any of these two cases: * If you want to report a bug, please do it in the corresponding forum * If you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile. == Postal address == G. Isabelli 19 bd république 92 260 Fontenay-aux-Roses FRANCE +33 6 17 25 80 34 e608e0a52f031694659de3f162e71fd4c20a7fff Contact 0 39 140 2012-06-27T18:40:51Z Een 3 Redirected page to [[Contact us]] wikitext text/x-wiki #REDIRECT [[Contact us]] 44227f4a379d1cb9c906fc5923f86e642d717086 Aboutus 0 40 141 2012-06-27T18:42:01Z Een 3 Redirected page to [[About us]] wikitext text/x-wiki #REDIRECT [[About us]] bb476bbb3a6b3eb744f44c0fbdfcb920954a6022 Gamehelpraceforthegalaxy 0 41 142 2012-06-28T09:06:10Z Spacediver 718 Created page with "You may drag a resource (single-coloured small card) to a consumption power to consume it." wikitext text/x-wiki You may drag a resource (single-coloured small card) to a consumption power to consume it. f221b6292998d419075a2a637383e0b7808e4b7a 143 142 2012-06-30T06:05:24Z Entropy2k 993 wikitext text/x-wiki In Race for the Galaxy, players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods, and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, consuming goods, and bonuses from special developments. There are 5 phases to choose from: explore, develop, settle, consume, and produce. Players pick 1 phase per turn ( two phases in a 2 player game), then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player plays 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most cards in hand wins. You may drag a resource (single-coloured small card) to a consumption power to consume it. 332ed8ac115c5b36871360de512d2523c65ceca7 Gamehelpdragonheart 0 31 144 96 2012-07-14T21:55:41Z Crazy c 1053 /* Cards */ wikitext text/x-wiki ==Summary== Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down. ==Goal== To have the most points by the end of the game. ==Game Start== At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board. ==End== The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 2 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game. ==Turns== Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship. ==Cards== There are five types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it is. Arrows on the board indicate what cards can take what. * ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf. * ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board. * ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards. * ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress. * ''Troll'': Placing this card allows the player to take the sorceress pile. * ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board. * ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent. * ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon. * ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the deck. The ship cards are then discarded. The third time that three ship cards are played ends the game and the opponent takes one final turn. * ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand. cb9673f3d13c9a0f1bbdc1666c6d3f1298f6486f 145 144 2012-07-14T21:57:15Z Crazy c 1053 /* End */ wikitext text/x-wiki ==Summary== Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down. ==Goal== To have the most points by the end of the game. ==Game Start== At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board. ==End== The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 3 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game. ==Turns== Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship. ==Cards== There are five types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it is. Arrows on the board indicate what cards can take what. * ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf. * ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board. * ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards. * ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress. * ''Troll'': Placing this card allows the player to take the sorceress pile. * ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board. * ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent. * ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon. * ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the deck. The ship cards are then discarded. The third time that three ship cards are played ends the game and the opponent takes one final turn. * ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand. e984bb914251f4a0f157c7a0785d53b3d4905237 146 145 2012-07-14T21:58:29Z Crazy c 1053 /* End */ wikitext text/x-wiki ==Summary== Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down. ==Goal== To have the most points by the end of the game. ==Game Start== At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board. ==End== The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 3 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game. In case of a tie, the player with the Great Dragon wins. ==Turns== Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship. ==Cards== There are five types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it is. Arrows on the board indicate what cards can take what. * ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf. * ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board. * ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards. * ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress. * ''Troll'': Placing this card allows the player to take the sorceress pile. * ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board. * ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent. * ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon. * ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the deck. The ship cards are then discarded. The third time that three ship cards are played ends the game and the opponent takes one final turn. * ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand. 3e0a5f8d9ad58be87706271bf73b4fcc52471ff6 Gamehelptobago 0 27 147 87 2012-07-19T06:49:54Z Crazy c 1053 /* 2) Move ATV from 1 to 3 legs */ wikitext text/x-wiki == Goal == Get as many gold coins as you can by locating treasures on the Tobago island and sharing them with other players. == Rules summary == On their turn, each player can choose one of two actions: ===1) Play a clue card from his hand=== The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue). Positioning clues are as follows: in, next to, in sight of, not in, not next to, not in sight of. When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type. When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map indicate where the treasure can be. When there is only one of these markers left, the treasure is located and can be raised. ===2) Move ATV from 1 to 3 legs=== A leg is a move of: * either as many spaces as you want in the same land type * or only one space when moving from one land type to another. When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. When a treasure is raised, the current move is finished, even if the player has not used all the legs to which he was entitled. Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure. Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards. An additional card is taken from the deck and the cards are shuffled. Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded. Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card. When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map. Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base. Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions: * play a clue card * remove a treasure marker * move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet) * to exchange the clue cards from his hand with clue cards from the deck Proper use of amulet power is critical to ensure victory! The game ends after the last treasure card has been given out. '''Have a good game !''' 162a27ee6a534e10c342b291885452d9fdf04053 148 147 2012-07-19T07:09:01Z Crazy c 1053 /* 1) Play a clue card from his hand */ wikitext text/x-wiki == Goal == Get as many gold coins as you can by locating treasures on the Tobago island and sharing them with other players. == Rules summary == On their turn, each player can choose one of two actions: ===1) Play a clue card from his hand=== The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue). Positioning clues are as follows: in, next to, in sight of, not in, not next to, not in sight of. When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type. The player can decide which treasure map he wants to play his clue card on. In order to play a clue card on a map you must make sure that: *The new clue card mustn't contradicted any present clue cards of the specific treasure map. *The new clue card must reduce at least one marker from the current amount of markers of the specific treasure map (if there are markers on the board. If there are no markers on the board, you can still put a clue card even if it doesn't change anything). *The new clue card must keep it possible for at least one marker to stay on the board (a treasure cannot disappear from the board). When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map are placed on the island, indicating where the treasure might be. When there is only one of these markers left, the treasure is located and can be raised. ===2) Move ATV from 1 to 3 legs=== A leg is a move of: * either as many spaces as you want in the same land type * or only one space when moving from one land type to another. When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. When a treasure is raised, the current move is finished, even if the player has not used all the legs to which he was entitled. Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure. Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards. An additional card is taken from the deck and the cards are shuffled. Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded. Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card. When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map. Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base. Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions: * play a clue card * remove a treasure marker * move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet) * to exchange the clue cards from his hand with clue cards from the deck Proper use of amulet power is critical to ensure victory! The game ends after the last treasure card has been given out. '''Have a good game !''' e77ddbfe3be6e45d3526a4e0ace96c704f87d2b8 Gamehelptobago 0 27 149 148 2012-07-19T07:10:35Z Crazy c 1053 /* Goal */ wikitext text/x-wiki == Goal == Be the player with the most gold coins by locating treasures on the Tobago island and/or sharing them with other players. == Rules summary == On their turn, each player can choose one of two actions: ===1) Play a clue card from his hand=== The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue). Positioning clues are as follows: in, next to, in sight of, not in, not next to, not in sight of. When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type. The player can decide which treasure map he wants to play his clue card on. In order to play a clue card on a map you must make sure that: *The new clue card mustn't contradicted any present clue cards of the specific treasure map. *The new clue card must reduce at least one marker from the current amount of markers of the specific treasure map (if there are markers on the board. If there are no markers on the board, you can still put a clue card even if it doesn't change anything). *The new clue card must keep it possible for at least one marker to stay on the board (a treasure cannot disappear from the board). When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map are placed on the island, indicating where the treasure might be. When there is only one of these markers left, the treasure is located and can be raised. ===2) Move ATV from 1 to 3 legs=== A leg is a move of: * either as many spaces as you want in the same land type * or only one space when moving from one land type to another. When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. When a treasure is raised, the current move is finished, even if the player has not used all the legs to which he was entitled. Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure. Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards. An additional card is taken from the deck and the cards are shuffled. Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded. Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card. When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map. Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base. Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions: * play a clue card * remove a treasure marker * move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet) * to exchange the clue cards from his hand with clue cards from the deck Proper use of amulet power is critical to ensure victory! The game ends after the last treasure card has been given out. '''Have a good game !''' 1349f4ae9b3bc89321b0a00622234f29a6611878 150 149 2012-07-19T07:22:16Z Crazy c 1053 /* 2) Move ATV from 1 to 3 legs */ wikitext text/x-wiki == Goal == Be the player with the most gold coins by locating treasures on the Tobago island and/or sharing them with other players. == Rules summary == On their turn, each player can choose one of two actions: ===1) Play a clue card from his hand=== The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue). Positioning clues are as follows: in, next to, in sight of, not in, not next to, not in sight of. When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type. The player can decide which treasure map he wants to play his clue card on. In order to play a clue card on a map you must make sure that: *The new clue card mustn't contradicted any present clue cards of the specific treasure map. *The new clue card must reduce at least one marker from the current amount of markers of the specific treasure map (if there are markers on the board. If there are no markers on the board, you can still put a clue card even if it doesn't change anything). *The new clue card must keep it possible for at least one marker to stay on the board (a treasure cannot disappear from the board). When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map are placed on the island, indicating where the treasure might be. When there is only one of these markers left, the treasure is located and can be raised. ===2) Move ATV from 1 to 3 legs=== A leg is a move of: * either as many spaces as you want in the same land type * or only one space when moving from one land type to another. ===3) Treasure sharing and amulets=== When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. Raising a treasure will end a player's turn, even if the player has not used all 3 legs. Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure. Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards. An additional card is taken from the deck and the cards are shuffled. Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded. Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card. When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map. Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base. Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions: * play a clue card * remove a treasure marker * move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet) * to exchange the clue cards from his hand with clue cards from the deck Proper use of amulet power is critical to ensure victory! ===End of the game=== The game ends after the last treasure card has been given out. '''Have a good game !''' 3006885193bc285203a8f1e9db8ee4f4e3a7c323 151 150 2012-07-19T07:28:59Z Crazy c 1053 /* End of the game */ wikitext text/x-wiki == Goal == Be the player with the most gold coins by locating treasures on the Tobago island and/or sharing them with other players. == Rules summary == On their turn, each player can choose one of two actions: ===1) Play a clue card from his hand=== The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue). Positioning clues are as follows: in, next to, in sight of, not in, not next to, not in sight of. When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type. The player can decide which treasure map he wants to play his clue card on. In order to play a clue card on a map you must make sure that: *The new clue card mustn't contradicted any present clue cards of the specific treasure map. *The new clue card must reduce at least one marker from the current amount of markers of the specific treasure map (if there are markers on the board. If there are no markers on the board, you can still put a clue card even if it doesn't change anything). *The new clue card must keep it possible for at least one marker to stay on the board (a treasure cannot disappear from the board). When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map are placed on the island, indicating where the treasure might be. When there is only one of these markers left, the treasure is located and can be raised. ===2) Move ATV from 1 to 3 legs=== A leg is a move of: * either as many spaces as you want in the same land type * or only one space when moving from one land type to another. ===3) Treasure sharing and amulets=== When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. Raising a treasure will end a player's turn, even if the player has not used all 3 legs. Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure. Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards. An additional card is taken from the deck and the cards are shuffled. Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded. Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card. When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map. Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base. Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions: * play a clue card * remove a treasure marker * move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet) * to exchange the clue cards from his hand with clue cards from the deck Proper use of amulet power is critical to ensure victory! ===End of the game=== The game ends when the treasure card pile runs out. '''Have a good game !''' dae010445287c763c8ab4bb06d1c09883e19707b 161 151 2012-08-27T23:39:45Z Villager 1295 /* 3) Treasure sharing and amulets */ wikitext text/x-wiki == Goal == Be the player with the most gold coins by locating treasures on the Tobago island and/or sharing them with other players. == Rules summary == On their turn, each player can choose one of two actions: ===1) Play a clue card from his hand=== The clue cards give the positioning of a treasure for a map of a given color relative to a land type (jungle, mountains, beach, scrubland, river, lake or sea) or to a landmark (palm tree, hut or statue). Positioning clues are as follows: in, next to, in sight of, not in, not next to, not in sight of. When the position is given relative to a land type, if there are red brackets above and below the land type it means that the land to use for this clue is the largest of this type. The player can decide which treasure map he wants to play his clue card on. In order to play a clue card on a map you must make sure that: *The new clue card mustn't contradicted any present clue cards of the specific treasure map. *The new clue card must reduce at least one marker from the current amount of markers of the specific treasure map (if there are markers on the board. If there are no markers on the board, you can still put a clue card even if it doesn't change anything). *The new clue card must keep it possible for at least one marker to stay on the board (a treasure cannot disappear from the board). When less than 17 spaces on the island match the clues for a treasure map, markers of the color of the map are placed on the island, indicating where the treasure might be. When there is only one of these markers left, the treasure is located and can be raised. ===2) Move ATV from 1 to 3 legs=== A leg is a move of: * either as many spaces as you want in the same land type * or only one space when moving from one land type to another. ===3) Treasure sharing and amulets=== When a player's ATV is on an island space containing an amulet, the player can pick it up. If the ATV is on a space containing a treasure that has been located, he can raise it, and then players have to share it. Raising a treasure will end a player's turn, even if the player has not used all 3 legs. Sharing of the treasure happens solely between the players who took part in its discovery, either by playing clue cards on the treasure map, or by raising the treasure. Each player is presented with as many treasure cards as they have windroses of their color representing their participation in the discovery of the treasure (a windrose is placed on each clue card that is played, and a windrose is also placed under the last clue card of the map for the player who raises the treasure). The other players do not see these cards. An additional card is taken from the deck and the cards are shuffled. Each player in turn, in the reverse order of placement of windroses on the treasure map, draws a card amidst those belonging to this treasure and chooses either to take it and withdraw his windrose from the map, or to give it to the next player (in the order set by the windroses as described before) who is then presented with the same choice. If no player accepts it, the treasure card is discarded. Two curse cards can be found among the treasure cards. If a curse card is drawn, treasure sharing is over, and all players who are still involved in sharing the treasure (ie players with windroses on the map for the treasure being shared) can either protect themselves by sacrificing an amulet, or lose their most valuable treasure card. When the treasure sharing is over, the last player to have been granted a treasure card must reopen the treasure hunt by playing one clue card for the now empty treasure map. Then, mysterious amulets appear where the gaze of statues strikes the coast, and statues rotate on their base. Once collected, an amulet can be spent at any time during a player's turn to do one of 4 possible actions: * play a clue card * remove a treasure marker * move his ATV three legs (NB: it is not possible to collect other amulets while moving thanks to an amulet.. BUT you can RAISE a treasure!) * to exchange the clue cards from his hand with clue cards from the deck Proper use of amulet power is critical to ensure victory! ===End of the game=== The game ends when the treasure card pile runs out. '''Have a good game !''' 953052c0da61d4fc18048a92604e5b53e2e54e84 Gamehelpdiams 0 38 152 134 2012-07-22T09:03:02Z Crazy c 1053 /* Special cards */ wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round : * for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) * and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory) == Rules summary == On your turn, you must first choose between two 'draw actions' (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two 'play actions' (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will loose yours!) '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (but of course, if your opponent doesn't have any diamond of this kind, drilling will fail!) '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game!''' 33228376d9a780183c2c7c45fc52dae361572e2d 153 152 2012-07-22T09:04:15Z Crazy c 1053 /* Special cards */ wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round : * for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) * and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2d gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2d round who will get the victory) == Rules summary == On your turn, you must first choose between two 'draw actions' (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two 'play actions' (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will lose yours!) '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (but of course, if your opponent doesn't have any diamond of this kind, drilling will fail!) '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game!''' 1129c9ce9f9cc7e7d942da196bfc69693fd04ca7 Gamehelpunitedsquare 0 42 154 2012-07-22T09:46:01Z Crazy c 1053 Created page with "===goal=== The goal is to be the player who has the most squares of his colors. ===rules=== The game contains multicolored squares (red, blue. yellow and green) which appear ..." wikitext text/x-wiki ===goal=== The goal is to be the player who has the most squares of his colors. ===rules=== The game contains multicolored squares (red, blue. yellow and green) which appear as 4 colored triangles on the square. Each player on his turn puts a multicolored square next to a square already on the board. The played square (which can be shifted to fit as requested, keeping the order of the colors the same) must be put in a way that creates at least on colored square (not necessarily your color). If it is not possible for the player to put down a square, the turn is passed to the next player. It is also possible to have "non playable" squares which are created when 2 of the same color are connected to the same open square. This is also a strategy to prevent from your opponent from getting more squares of his color. (e.g. if there is a red triangle facing an empty square and i connect to that same empty square another red triangle from another side, the empty square cannot be played and all colors around the "non playable" square will not become squares and won't gain points). ===ending the gsme=== When all playable squares have been played, the player with the most squares of his color wins the game. HAVE A GOOD GAME! 69c010a69b9893a52e587fba072f34ad0c9fbb12 155 154 2012-07-22T09:46:59Z Crazy c 1053 /* ending the gsme */ wikitext text/x-wiki ===goal=== The goal is to be the player who has the most squares of his colors. ===rules=== The game contains multicolored squares (red, blue. yellow and green) which appear as 4 colored triangles on the square. Each player on his turn puts a multicolored square next to a square already on the board. The played square (which can be shifted to fit as requested, keeping the order of the colors the same) must be put in a way that creates at least on colored square (not necessarily your color). If it is not possible for the player to put down a square, the turn is passed to the next player. It is also possible to have "non playable" squares which are created when 2 of the same color are connected to the same open square. This is also a strategy to prevent from your opponent from getting more squares of his color. (e.g. if there is a red triangle facing an empty square and i connect to that same empty square another red triangle from another side, the empty square cannot be played and all colors around the "non playable" square will not become squares and won't gain points). ===ending the game=== When all playable squares have been played, the player with the most squares of his color wins the game. HAVE A GOOD GAME! fc984f3d37b1db341a2475115260c766cf2def67 Gamehelpseasons 0 43 156 2012-08-13T15:53:58Z Jolelaw 1170 Game help for Season Board Game wikitext text/x-wiki Season is a game of generating points (crystal) by choosing the correct combination of dice and the activation of card powers. The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be return to the player on the starting of each cycle. Each player can choose only one die per turn. The effects are as follows: Star - increase the maximum card player can summon (max 15) Elements - Gain an energy of the element shown (water, earth, air, fire) Numbers - Gain the number of Crystals as indicated by the number Square card - Draw a card Dice with frames surrounding - Allow user to transmute energy into crystal (depend on which part of the game is at) Dots - Indicate how fast the marker progress through the seasons cycle There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There is 4 type of helps which include adding a star, allow user to transmute this turn, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice). At the end of the game the points are calculated by adding the numbers on each card and the crystal owned. The player with the most victory points wins. Note: Users need to discard energy immediately if the energy is more than the slots allocated. Card summon by other card but due to limitation of the star will cause the new card to be discarded, no refund. ad8bf0ef8a56d186cb4e1a72485c86c9a94fb6ca 157 156 2012-08-13T15:55:10Z Jolelaw 1170 wikitext text/x-wiki Season is a game of generating points (crystal) by choosing the correct combination of dice and the activation of card powers. The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be return to the player on the starting of each cycle. Each player can choose only one die per turn. The effects are as follows: Star - increase the maximum card player can summon (max 15) Elements - Gain an energy of the element shown (water, earth, air, fire) Numbers - Gain the number of Crystals as indicated by the number Square card - Draw a card Dice with frames surrounding - Allow user to transmute energy into crystal (depend on which part of the game is at) Dots - Indicate how fast the marker progress through the seasons cycle There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There is 4 type of helps which include adding a star, allow user to transmute this turn, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice). At the end of the game the points are calculated by adding the numbers on each card and the crystal owned. The player with the most victory points wins. Note: Users need to discard energy immediately if the energy is more than the slots allocated. Card summon by other card but due to limitation of the star will cause the new card to be discarded, no refund. 52bce609540fca265df665f782174a6e635e6c51 185 157 2012-09-21T07:54:53Z Talia 1349 Appending description of the Transmute +1 bonus action. wikitext text/x-wiki Season is a game of generating points (crystal) by choosing the correct combination of dice and the activation of card powers. The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be return to the player on the starting of each cycle. Each player can choose only one die per turn. The effects are as follows: Star - increase the maximum card player can summon (max 15) Elements - Gain an energy of the element shown (water, earth, air, fire) Numbers - Gain the number of Crystals as indicated by the number Square card - Draw a card Dice with frames surrounding - Allow user to transmute energy into crystal (depend on which part of the game is at) Dots - Indicate how fast the marker progress through the seasons cycle There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There is 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice). At the end of the game the points are calculated by adding the numbers on each card and the crystal owned. The player with the most victory points wins. Note: Users need to discard energy immediately if the energy is more than the slots allocated. Card summon by other card but due to limitation of the star will cause the new card to be discarded, no refund. aad2a6045db9fb9588409b7c8abd0a0a8e134f43 About us 0 6 158 27 2012-08-15T04:17:28Z Suds307 1213 wikitext text/x-wiki First, we should say that we are gamers. Real, complete boardgames addicts. We designed '''Board Game Arena''' for players who can't play for real because of time, geographic or social constraints. We would like to provide a new game experience with the best of two worlds: video games and board games. Although we aim to provide high quality online games, we are still convinced that the best way to enjoy board games is around a *real* table with friends. This is one of the reason we strongly recommend you to buy physical copies of the games you discover on BGA. The other reason is simple to understand: each game sale is also a revenue for an author and an editor (... we've come full circle). [[Contact us]] 3df742bb9998193b9edd78eb592b6c63e09eb5fd Translation guidelines 0 18 159 68 2012-08-19T18:58:42Z Rokras 1237 /* I fixed some translations, but they don't appear to have changed on the site */ wikitext text/x-wiki The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena into any language, in order to enable more people to discover and play board games, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10-year-old nephew and he doesn't speak English yet, no problem! Just help us translate Board Game Arena into your language! == What can be translated? == Every string of text for the main site interface and for the games' interfaces are 'internationalized' and can be translated. For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometime later... == Who should translate? == This is important: only translate text into a given language if you are a native speaker of the language. When translating a game, the translator should know the game thoroughly and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronominal rules usual for the gaming audience of their country. As Board Game Arena's team's mother tongue is French, we will take charge of the French translations. We will also release the first version of the English translation. As we are not perfect speakers of Shakespeare's language, these translations will be open for review and correction by native English speakers under the same conditions as the other languages. == About context == Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot incorrect forms (if any) while playing and be able to correct them. Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information. == When will the site be made available in a new language it is being translated into? == As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in the language. == I fixed some translations, but they don't appear to have changed on the site == Translation files are updated nightly, so you just have to wait till the tomorrow for your changes to appear on the site. == How long will it be possible to change the translations? == The first translations may not be perfect (as explained in the 'about context' section). So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore. == Is there some reward for translating? == Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated). This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all! == Translation tips == * Use the 'TAB' key to go from one text box to another. This is easier than clicking. * Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}). * When in doubt, leave a comment for the next translator. * When you fix someone's translation, leave a comment if the reason for the change is not obvious. * When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing. 39afad37613aa3eedd26702970c7420d0a87fc44 Reputation 0 17 160 73 2012-08-27T02:15:45Z Villager 1295 /* How to increase my reputation / what makes my reputation decrease ? */ wikitext text/x-wiki [[Category:Help]] == What is reputation ? == On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance. To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items: * Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png) * % of games you finished * % of games you finished with no clock penalties Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits. == How to increase my reputation / what makes my reputation decrease ? == At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks. * a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player. * a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player. You can only give a single thumb (green or red) to a single player. If your opinion evolved you can click again on a thumb to reflect this change. As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended to leave the game or to expel this player. By nature, opinions are subjectives. There is nothing we can do for you if you receive a for an unfair reason. However, we know by experience that this system has a lot of advantages and give a relevant information. Qn: its unclear if the "> 10% unfavorable" warning is calculated against the number of "thumbs up / thumbs down".. or "total number of unique players played with / thumbs down". Hope the formula is the latter.. as the first formula will raise many more warnings.. more idiots give thumbs down, and are lazier to give thumb up. == Advices: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png == * Be polite ! Say at least "hello" and "good luck" at the beginning of the game. "good game" ("gg") at the end of the game. * When you need some time to think, click on "I would like to think a little" link. * Stay calm in any circumstances: it's a game. * Don't press your opponent to play if he has some time left. * If you really can't finish the game (this is not supposed to happened...), then say you are sorry and leave the game by your own to save your opponents time. * Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!). * Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation. == What are the consequences of a bad reputation ? == A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you. It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents. d9004c71be8151f6e6ca1166b60f3f1e209e452c 165 160 2012-09-08T18:11:50Z Complete muppet 1365 /* Advices: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png */ wikitext text/x-wiki [[Category:Help]] == What is reputation ? == On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance. To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items: * Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png) * % of games you finished * % of games you finished with no clock penalties Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits. == How to increase my reputation / what makes my reputation decrease ? == At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks. * a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player. * a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player. You can only give a single thumb (green or red) to a single player. If your opinion evolved you can click again on a thumb to reflect this change. As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended to leave the game or to expel this player. By nature, opinions are subjectives. There is nothing we can do for you if you receive a for an unfair reason. However, we know by experience that this system has a lot of advantages and give a relevant information. Qn: its unclear if the "> 10% unfavorable" warning is calculated against the number of "thumbs up / thumbs down".. or "total number of unique players played with / thumbs down". Hope the formula is the latter.. as the first formula will raise many more warnings.. more idiots give thumbs down, and are lazier to give thumb up. == Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png == * Be polite! Say at least "hello" and "good luck" at the beginning of the game, and maybe "good game" ("gg") at the end of the game. * When you need some time to think, click on "I would like to think a little" link. * Always stay calm: it's a game. * Don't press your opponent to play if he has some time left. * If you really can't finish the game (this is not supposed to happen...), then say you are sorry and leave the game (don't wait to get expelled) to save your opponents time. * Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!). * Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation. == What are the consequences of a bad reputation ? == A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you. It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents. 7dd2d7d9b84788c2193110bb923f60b6b20dec5b Game clock 0 15 162 34 2012-09-08T18:06:25Z Complete muppet 1365 /* Time to think */ wikitext text/x-wiki [[Category:Help]] On '''Board Game Arena''' you are playing "live" (real time). Then you has a delay to play your moves. Your initial delay at the beginning of a game is most of the time '''3 minutes'''. At each turn, or on specific occasion, you get an additional delay. If you have no more time to play, you will get a penalty and can become eligible to be expelled from the game. == Time to think == Your alloted time to think is displayed on the right of your player's name. When it's your turn to play. This time is also displayed at the top of the web page. == Game speed == Table administrator can make a choice between 4 game speed profile: * Fast * Normal * Slow * Without time limit The additional amount of time credited each turn depends on chosen game speed profile. Be careful to check game speed before game start to adapt your timing. Note: playing without time limit is strongly discouraged, except if you are playing with friends or to discover a new game. Remember that without time limit, you can't expel a player that stops playing. == Running out of time == As soon as you run out of time, you get a clock penalty. If you goes over your alloted time by more than 3/4/5 minutes (depending on game speed), any opponent can expel you from the game. Of course, it is strongly advised not to run out of time ... == Move time limit == In addition to your classical time to think, you have a limited time alloted for each move. When it's your turn to play, a red bar appears on top of the web page. It symbolized the remaining time limit for this move. The amount of time depends on game speed. If you goes over this limit, you become eligible to be expelled from the game. == "My opponent is too slow" == Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his alloted time to think. If you want to play fast, set up or join table with "fast" mode only, but don't force an opponent to play when he has the right to do so. == "I would like to think a little" == If you are in a critical step of the game and want to take some time to think, you can click on the link "I would like to think a little" on the top right of the page. Thus, your opponents will receive a message and won't be thinking you are away from keyboard. Clicking on this link is not mandatory, but we encourage its use for courtesy. 5d8716bd998afb9592ab1dc42cf952b41d0cb657 163 162 2012-09-08T18:06:47Z Complete muppet 1365 /* Time to think */ wikitext text/x-wiki [[Category:Help]] On '''Board Game Arena''' you are playing "live" (real time). Then you has a delay to play your moves. Your initial delay at the beginning of a game is most of the time '''3 minutes'''. At each turn, or on specific occasion, you get an additional delay. If you have no more time to play, you will get a penalty and can become eligible to be expelled from the game. == Time to think == Your alloted time to think is displayed on the right of your player's name. When it's your turn to play, this time is also displayed at the top of the web page. == Game speed == Table administrator can make a choice between 4 game speed profile: * Fast * Normal * Slow * Without time limit The additional amount of time credited each turn depends on chosen game speed profile. Be careful to check game speed before game start to adapt your timing. Note: playing without time limit is strongly discouraged, except if you are playing with friends or to discover a new game. Remember that without time limit, you can't expel a player that stops playing. == Running out of time == As soon as you run out of time, you get a clock penalty. If you goes over your alloted time by more than 3/4/5 minutes (depending on game speed), any opponent can expel you from the game. Of course, it is strongly advised not to run out of time ... == Move time limit == In addition to your classical time to think, you have a limited time alloted for each move. When it's your turn to play, a red bar appears on top of the web page. It symbolized the remaining time limit for this move. The amount of time depends on game speed. If you goes over this limit, you become eligible to be expelled from the game. == "My opponent is too slow" == Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his alloted time to think. If you want to play fast, set up or join table with "fast" mode only, but don't force an opponent to play when he has the right to do so. == "I would like to think a little" == If you are in a critical step of the game and want to take some time to think, you can click on the link "I would like to think a little" on the top right of the page. Thus, your opponents will receive a message and won't be thinking you are away from keyboard. Clicking on this link is not mandatory, but we encourage its use for courtesy. 7995e4abd5d929043908bb375a931bc0fc50a79b 164 163 2012-09-08T18:09:41Z Complete muppet 1365 wikitext text/x-wiki [[Category:Help]] On '''Board Game Arena''' you are playing "live" (real time). That means you have an allotted delay to play your moves. Most of the time, your initial delay at the beginning of a game is '''3 minutes'''. During each turn, or on specific occasions, you get an additional delay. If you have no more time to play, you will get a penalty and can become eligible to be expelled from the game. == Time to think == Your allotted time to think is displayed on the right of your player's name. When it's your turn to play, this time is also displayed at the top of the web page. == Game speed == Table administrator can make a choice between 4 game speed profile: * Fast * Normal * Slow * Without time limit The additional amount of time credited each turn depends on chosen game speed profile. Be careful to check game speed before game start to adapt your timing. Note: playing without time limit is strongly discouraged, except if you are playing with friends or to discover a new game. Remember that without time limit, you can't expel a player that stops playing. == Running out of time == As soon as you run out of time, you get a clock penalty. If you goes over your alloted time by more than 3/4/5 minutes (depending on game speed), any opponent can expel you from the game. Of course, it is strongly advised not to run out of time ... == Move time limit == In addition to your classical time to think, you have a limited time alloted for each move. When it's your turn to play, a red bar appears on top of the web page. It symbolized the remaining time limit for this move. The amount of time depends on game speed. If you go over this limit, you become eligible to be expelled from the game. == "My opponent is too slow" == Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his allotted time to think. If you want to play fast, set up or join table with "fast" mode only, but don't force an opponent to play when he has the right to do so. == "I would like to think a little" == If you are in a critical step of the game and want to take some time to think, you can click on the link "I would like to think a little" on the top right of the page. Thus, your opponents will receive a message and won't be thinking you are away from keyboard. Clicking on this link is not mandatory, but we encourage its use for courtesy. 8e7b80d9cbd9b3f6552a666e0ca9793092c8f5b3 Gamehelpcolorpop 0 44 166 2012-09-08T18:33:11Z Davejhave 776 Created page with "Select adjacent colored tokens in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped. White tokens..." wikitext text/x-wiki Select adjacent colored tokens in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped. White tokens can be used as any color. You must pop all adjacent tokens of the same color. 0a4173a50ab5172c145b15e28e7a9496b9078db5 167 166 2012-09-08T18:47:19Z Davejhave 776 wikitext text/x-wiki Select adjacent colored tokens in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped. White tokens can be used as any color. Win instantaly by popping all of your secret colored tokens. You must pop all adjacent tokens of the same color. 17b1fb1d81ac204da6e965e9ebd8afcd310f6572 168 167 2012-09-09T12:32:33Z Een 3 wikitext text/x-wiki == The game == Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped. White tokens can be used as '''any color'''. Win '''instantly''' by popping all of your secret colored tokens. You must pop '''all''' adjacent tokens of the same color. == Variants == '''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games. NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic. == Game preferences == The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva ([http://www.coloradd.net/ ColorADD]). '''Have a good game!''' 3718a603bfcba24969ed526d679dae1232da348f 169 168 2012-09-09T12:35:06Z Een 3 wikitext text/x-wiki == The game == Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped. White tokens can be used as '''any color'''. Win '''instantly''' by popping all of your secret colored tokens. You must pop '''all''' adjacent tokens of the same color. In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins. == Variants == '''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games. NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic. == Game preferences == The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva ([http://www.coloradd.net/ ColorADD]). '''Have a good game!''' 4b8ed1d1192e2176b1da8b8aa75ef605b7c580d4 171 169 2012-09-12T19:55:55Z Een 3 wikitext text/x-wiki == The game == Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped. White tokens can be used as '''any color'''. Win '''instantly''' by popping all of your secret colored tokens. You must pop '''all''' adjacent tokens of the same color. In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins. == Variants == '''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games. NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic. == Game preferences == The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva ([http://www.coloradd.net/code.asp ColorADD]). '''Have a good game!''' 612b122320e94857a200782521a758ad2c11d445 172 171 2012-09-12T20:00:14Z Een 3 wikitext text/x-wiki == The game == Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped. White tokens can be used as '''any color'''. Win '''instantly''' by popping all of your secret colored tokens. You must pop '''all''' adjacent tokens of the same color. In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins. == Variants == '''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games. NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic. == Game preferences == The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD]. '''Have a good game!''' 34a5c561d3d6540c63bcd99833acc93d4ba5e571 174 172 2012-09-13T17:38:36Z Een 3 /* Game preferences */ wikitext text/x-wiki == The game == Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped. White tokens can be used as '''any color'''. Win '''instantly''' by popping all of your secret colored tokens. You must pop '''all''' adjacent tokens of the same color. In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins. == Variants == '''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games. NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic. == Game preferences == The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD]. Learning the code is easy, just take a look at the following synthesis panel: [[File:ColorADD.jpg]] '''Have a good game!''' c1faf3ca99a6d1d9fedff47d69fd8f5b5f3a6f10 175 174 2012-09-13T17:46:08Z Een 3 /* Game preferences */ wikitext text/x-wiki == The game == Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped. White tokens can be used as '''any color'''. Win '''instantly''' by popping all of your secret colored tokens. You must pop '''all''' adjacent tokens of the same color. In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins. == Variants == '''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games. NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic. == Game preferences == The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD]. Learning the code is easy, just take a look at the following synthesis panel: [[File:ColorADD.jpg]] <img alt="Synthesis panel" src="http://en.doc.boardgamearena.com/images/0/0b/ColorADD.jpg" /> '''Have a good game!''' 16f73ad1be3268a2aa7f75f33fc0f84e0fd90b8b 176 175 2012-09-13T17:49:20Z Een 3 /* Game preferences */ wikitext text/x-wiki == The game == Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped. White tokens can be used as '''any color'''. Win '''instantly''' by popping all of your secret colored tokens. You must pop '''all''' adjacent tokens of the same color. In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins. == Variants == '''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games. NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic. == Game preferences == The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD]. Learning the code is easy, just take a look at the following synthesis panel: [[File:ColorADD.jpg]] '''Have a good game!''' c1faf3ca99a6d1d9fedff47d69fd8f5b5f3a6f10 179 176 2012-09-13T19:32:14Z Een 3 /* Game preferences */ wikitext text/x-wiki == The game == Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped. White tokens can be used as '''any color'''. Win '''instantly''' by popping all of your secret colored tokens. You must pop '''all''' adjacent tokens of the same color. In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins. == Variants == '''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games. NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic. == Game preferences == The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD]. Learning the code is easy, just take a look at the following synthesis panel: [[File:ColorADD.jpg]] '''Have a good game!''' fa6b2c12165602be9a3d3f3d21a480c5460e4f6d 180 179 2012-09-13T19:32:32Z Een 3 /* Game preferences */ wikitext text/x-wiki == The game == Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped. White tokens can be used as '''any color'''. Win '''instantly''' by popping all of your secret colored tokens. You must pop '''all''' adjacent tokens of the same color. In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins. == Variants == '''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games. NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic. == Game preferences == The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD]. Learning the code is easy, just take a look at the following synthesis panel: [[File:ColorADD.jpg]] '''Have a good game!''' def489ae3d57eb9d1faf5a66fbb586c277361faa 181 180 2012-09-13T19:33:10Z Een 3 /* Game preferences */ wikitext text/x-wiki == The game == Select '''adjacent colored tokens''' in order to pop them. Strategically pop colored tokens in order to finish the game with the most of your own secret color popped. White tokens can be used as '''any color'''. Win '''instantly''' by popping all of your secret colored tokens. You must pop '''all''' adjacent tokens of the same color. In case of a tie at the end of the game, it's the player who popped '''the less''' of the tokens matching his own secret color who wins. == Variants == '''Two secret colors''': this variant allows you to play Color Pop with two secret colors, which will have you thinking very often on which color you are gonna favor this turn! This variant is only available for two player games. NB : you can also '''play against the computer''' and try to win '''solo challenges''' on the [http://www.colorpop-online.com www.colorpop-online.com] website hosted by the game publisher, Gigamic. == Game preferences == The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD]. Learning the code is easy, just take a look at the following synthesis panel: [[File:ColorADD.jpg]] '''Have a good game!''' ee464ecfaa154f5d4bfc530f7fa81ec68dcbea69 Gamehelpcantstop 0 35 170 93 2012-09-10T02:58:19Z Wmlwmsh 1387 wikitext text/x-wiki Can't Stop is a very easy and fast game! '''How to play''' Roll 4 standard dice and then choose the sums of any 2 dice to advance your position on the board. You are allowed to use 3 temporary markers to track your progress in columns marked 2 through 12. These markers are commonly white or black. You can continue to roll the dice hoping to roll one of the previous combinations in the three columns selected this turn. When you think you've pushed your luck far enough you say "STOP" then pass the dice to the next player and replace the white markers with your own. If you roll the dice and find no useful combination you fail and your progress is lost. The more common numbers on 2d6 (6,7 and 8) have more steps in their paths while the less common combinations (2 and 12) have less. '''The object of the game is''' to reach and cover 3 peaks of these columns! 欲罷不能 如何進行遊戲 首先擲出四顆骰子,之後把四顆骰子兩兩分組配成可以搭配的任意數字(2~12),之後選擇其中一種配對執行。 執行時你可以擁有三個暫時的標記物可以作為前進的工具(此回合超過第三個就不能選該組合中的該項數值,但是其中一項可以前進即可選擇,另外一總組合則視同放棄) 重複以上動作直到你覺得這回合你前進已經夠了或是擲出你沒有辦法前進的骰子點數組合則該回合結束 若是自己喊出「夠了」則在現有的暫時標記物的位置換成自己的標記物輪下一人進行 若是因為擲出不能前進的骰子組合則是本回合前進的格數全部作廢依然換下一人進行回合 遊戲中使用的是兩個六面骰,依照組合的出現機率不同,在不同組合上要攻頂的需求步數也不同(例如7就需要最多格,因為他的出現率最高,相對的比較難出現的2.12就只需要短短的三格) 遊戲獲勝條件是其中有一人佔領了三條路線後則遊戲結束,由佔領三條路線的人獲勝 ea154f34371b9cb6ccc214ccbd3593b52dd35281 Restr:ColorADD.jpg 6 45 173 2012-09-13T17:36:42Z Een 3 ColorADD Synthesis Panel wikitext text/x-wiki ColorADD Synthesis Panel b91230a1bcd980ad210bfef7eda6568197448d37 177 173 2012-09-13T17:53:14Z Een 3 uploaded a new version of &quot;[[File:ColorADD.jpg]]&quot; wikitext text/x-wiki ColorADD Synthesis Panel b91230a1bcd980ad210bfef7eda6568197448d37 178 177 2012-09-13T17:55:55Z Een 3 uploaded a new version of &quot;[[File:ColorADD.jpg]]&quot; wikitext text/x-wiki ColorADD Synthesis Panel b91230a1bcd980ad210bfef7eda6568197448d37 Rating 0 16 182 107 2012-09-14T13:37:14Z Anthonyw 1416 /* How many points do I gain / lose for each game ? */ wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game ? == ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples: * If you end the game at a better place than a player with a higher ELO, you gain a lot of points. * If you end the game at a better place than a player with a lower ELO, you gain less points. * If you end the game at a worse place than a player with a lower ELO, you lose a lot points. * And so on... == Some advice == * There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO. * The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win. * The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you loose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent. == How is my ELO ranking computed ? == The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied. ELO system on BGA has some specificity: * During your first 30 games, your ELO rating is more "elastic": you can win (or loose) more points at each game. This way, your ELO rating converge faster to you "natural" rating. * Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you loose a 2-player game against each opponent before you (in game rank). * Games with more than 2 players last longer. For this reason, there's more points to win (or loose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula ! == The formula is exactly one's used by the ELO rating system, with the following adjustments: * At first, when someone left a game for any reason this game is not taken into account by the ELO rating system. * K=60 for the first 30 games, K=40 afterwards. * K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players". * If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600. == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO ac5f5c52715ee05bbf2d34ef4e9b941c675c66ba 183 182 2012-09-14T13:38:46Z Anthonyw 1416 /* How is my ELO ranking computed ? */ wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game ? == ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples: * If you end the game at a better place than a player with a higher ELO, you gain a lot of points. * If you end the game at a better place than a player with a lower ELO, you gain less points. * If you end the game at a worse place than a player with a lower ELO, you lose a lot points. * And so on... == Some advice == * There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO. * The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win. * The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you loose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent. == How is my ELO ranking computed ? == The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied. ELO system on BGA has some specificity: * During your first 30 games, your ELO rating is more "elastic": you can win (or lose) more points at each game. This way, your ELO rating converge faster to you "natural" rating. * Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you lose a 2-player game against each opponent before you (in game rank). * Games with more than 2 players last longer. For this reason, there's more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula ! == The formula is exactly one's used by the ELO rating system, with the following adjustments: * At first, when someone left a game for any reason this game is not taken into account by the ELO rating system. * K=60 for the first 30 games, K=40 afterwards. * K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players". * If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600. == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO 5b02a5186bab27aa010cb24915cd423d1d4d795c 184 183 2012-09-14T13:39:14Z Anthonyw 1416 /* Some advice */ wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game ? == ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples: * If you end the game at a better place than a player with a higher ELO, you gain a lot of points. * If you end the game at a better place than a player with a lower ELO, you gain less points. * If you end the game at a worse place than a player with a lower ELO, you lose a lot points. * And so on... == Some advice == * There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO. * The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win. * The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you lose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent. == How is my ELO ranking computed ? == The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied. ELO system on BGA has some specificity: * During your first 30 games, your ELO rating is more "elastic": you can win (or lose) more points at each game. This way, your ELO rating converge faster to you "natural" rating. * Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you lose a 2-player game against each opponent before you (in game rank). * Games with more than 2 players last longer. For this reason, there's more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula ! == The formula is exactly one's used by the ELO rating system, with the following adjustments: * At first, when someone left a game for any reason this game is not taken into account by the ELO rating system. * K=60 for the first 30 games, K=40 afterwards. * K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players". * If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600. == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO 29eee9580bc23d4a4b15f58a2c641902fc4e17bc The Boss 0 46 186 2012-10-08T03:20:42Z Surgeonufo 992 Created page with "Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden u..." wikitext text/x-wiki Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each play: 1) May place gangsters on a city; the large gangsters are returned at the end of each round, while the small ones are not. After placing the gangsters, you must have more of them than any opponent. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, flip over the police card. This will be the final round if there are 3 police symbols of the same color. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 2 turns. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. BEGINNER TIPS The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. bf53f1c840b684fa8d44a92ff430b74457a9ad71 187 186 2012-10-08T03:30:16Z Surgeonufo 992 wikitext text/x-wiki Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city; the large gangsters are returned at the end of each round, while the small ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, flip over the police card. This will be the final round if there are 3 police symbols of the same color. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 2 turns. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. BEGINNER TIPS The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. 72e05d23ee671ebfc3e694b7701c429bd6adb695 188 187 2012-10-08T03:58:44Z Surgeonufo 992 wikitext text/x-wiki Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city; the large gangsters are returned at the end of each round, while the small ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, flip over the police card. This will be the final round if there are 3 police symbols of the same color. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 2 turns. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. BEGINNER TIPS The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. 0984ee8026d2b253a4505a17cc83008844ab701f 189 188 2012-10-10T00:35:14Z Surgeonufo 992 wikitext text/x-wiki Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city; the large gangsters are returned at the end of each round, while the small ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, flip over the police card. This will be the final round if there are 3 police symbols of the same color. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. BEGINNER TIPS The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. 1cd0608a6589ed0b110ea3d8a710fecfac78d2cd 194 189 2012-10-21T16:41:16Z Zkiller 1253 wikitext text/x-wiki Description == Headline text == Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, flip over the police card. This will be the final round if there are 3 police symbols of the same color. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. BEGINNER TIPS The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. 7218e79b6f4ffa499d10c3c79258f17d0df6cea1 195 194 2012-10-21T16:41:46Z Zkiller 1253 wikitext text/x-wiki Description Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, flip over the police card. This will be the final round if there are 3 police symbols of the same color. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. BEGINNER TIPS The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. 2d47a12f90977587d13ecf3b85fc415bb6a0e154 196 195 2012-10-21T16:42:15Z Zkiller 1253 wikitext text/x-wiki Description Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, flip over the police card. This will be the final round if there are 3 police symbols of the same color. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. BEGINNER TIPS The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. c999bf38999a5f8e8cb1a90ca507e252c3b2823c 197 196 2012-10-21T16:50:12Z Zkiller 1253 wikitext text/x-wiki Description Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. BEGINNER TIPS The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. bb04a8cb3402651b892b179ee2ebca895c2383a3 198 197 2012-10-21T16:56:52Z Zkiller 1253 wikitext text/x-wiki == Goal == Be the player with the most money at the end of the game. At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. == Description == Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. BEGINNER TIPS The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. 432dfa10f670d4f18e73cc081f9ca0c85fa6c5b2 Development 0 47 190 2012-10-10T19:53:06Z Een 3 Created page with "== TODO ==" wikitext text/x-wiki == TODO == e1ac7bc92296781c3f0c5713f7149c6d5fe6804f Help 0 4 191 77 2012-10-11T00:52:25Z Surgeonufo 992 /* Games */ wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena]] ** [[About us]] ** [[Club Board Game Arena]] ** [[Contact us]] === Detailed help === * [[Getting started]] * [[Referral]] * [[Browser support]] * [[Moderation and grades]] * [[Game clock]] * [[Rating]] * [[Reputation]] * [[Translation guidelines]] == Games == * [[Gamehelphaggis|Haggis]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelpdominion|Dominion]] * [[Gamehelpyearofthedragon|In the Year of the Dragon]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelptroyes|Troyes]] * [[Gamehelpgosu|Gosu]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelpamyitis|Amyitis]] * [[Gamehelptobago|Tobago]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpunclechesnutstablegype|Uncle Chesnut's Table Gype]] * [[Gamehelptheboss]] 0174c39e1b6df9275ad2ba8f3ecaf2a6edaadb52 Gamehelpcoloretto 0 33 192 86 2012-10-12T06:06:20Z Texkill 1265 wikitext text/x-wiki While the regular game requires you to decide which piles to score positive/negative and where to place the jokers, this version automates that to give you the highest score possible. b9d4a44f0c124786a751dca5b76d3352df39041a Gamehelpraceforthegalaxy 0 41 193 143 2012-10-12T15:13:03Z Ksasaki 1566 wikitext text/x-wiki In Race for the Galaxy, players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods, and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, consuming goods, and bonuses from special developments. There are 5 phases to choose from: explore, develop, settle, consume, and produce. Players pick 1 phase per turn ( two phases in a 2 player game), then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player plays 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins. You may drag a resource (single-coloured small card) to a consumption power to consume it. abca15cea5052494619b6d5f1d5ba12ae3d0805c The Boss 0 46 199 198 2012-10-21T16:59:09Z Zkiller 1253 wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game. == Description == Each city, except Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. CHICAGO: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. BEGINNER TIPS The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. c19d7496df06f0519437e32618a00b0d1772c5bc 200 199 2012-10-21T17:01:57Z Zkiller 1253 wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game. == Description == Each city, except Chicago*, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. Chicago* city: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. BEGINNER TIPS The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. a6efd2dc5d10193fb18c67e46893ebc0795fe90f 201 200 2012-10-21T17:03:05Z Zkiller 1253 wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except *Chicago, has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. *Chicago: Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. BEGINNER TIPS The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. 68de3fcea9657fd8d02ccb5635c83e6c62065b91 202 201 2012-10-21T17:03:43Z Zkiller 1253 wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. BEGINNER TIPS The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. 7d6daad93cb2c130391c731332e7aacde688aad8 203 202 2012-10-21T17:03:59Z Zkiller 1253 wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. BEGINNER TIPS The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. 7c6b37bc7ca7145555d5c1f1ade750f39b1a0a7f 204 203 2012-10-21T17:05:02Z Zkiller 1253 wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. == Beginner Tips == The cards for each city are listed at the bottom, so if you have 3 Boston cards or 2 Philly cards you know a lot about what those cities are likely to be. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. 2a2298bf5bd374e53398e5cfb1215e89d24d339b 205 204 2012-10-21T17:07:02Z Zkiller 1253 wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. 8fd168878a6d30bb8a84c55609644fcef118bdcc 206 205 2012-10-21T17:08:29Z Zkiller 1253 wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. 071d649f531f765999f2a75340a28612fb75676f 207 206 2012-10-21T17:09:08Z Zkiller 1253 wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. *If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. b36f7ba25cf6739be80f8c65b37507f849d68230 208 207 2012-10-21T17:09:22Z Zkiller 1253 wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. *If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. f89411ca7e04c9d264393ef1174ff70d77d55cc7 209 208 2012-10-21T17:09:50Z Zkiller 1253 wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. *If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. ac01719485336c4476e486c5b66a0948146bb834 210 209 2012-10-21T17:13:33Z Zkiller 1253 wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. *If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. 15927b932ec12efb6e7c759531bd55c4c47aa256 211 210 2012-10-21T17:15:26Z Zkiller 1253 /* Description */ wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. === End === When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. *If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. fbb0032ad54b25bf8e79797d9caf16f06c92d337 212 211 2012-10-21T17:16:04Z Zkiller 1253 /* Description */ wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. === End === When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. *If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. 8a2f3be62a5d4dfa60387a18b4294141548a054e 213 212 2012-10-21T17:16:57Z Zkiller 1253 wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. === End === When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. *If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. ad560d07ee3da3a29fd361d5f71106e7d7da192c 214 213 2012-10-21T17:17:18Z Zkiller 1253 wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. === End === When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. *If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. be896aa3e963c564804a2ad2687dd5f142db909b 215 214 2012-10-21T17:18:18Z Zkiller 1253 /* Description */ wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. *If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. 0ac56904907b213c1616a11bbaa9c40d0d45a0a2 216 215 2012-10-21T17:18:52Z Zkiller 1253 /* Description */ wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. *If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. 216df9ddb16c37d4791196cf9503d42bd9c7b533 217 216 2012-10-21T18:32:21Z Zkiller 1253 moved [[Gamehelptheboss]] to [[The Boss]]: changing the temporary name wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. *If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. 216df9ddb16c37d4791196cf9503d42bd9c7b533 Gamehelptheboss 0 48 218 2012-10-21T18:32:21Z Zkiller 1253 moved [[Gamehelptheboss]] to [[The Boss]]: changing the temporary name wikitext text/x-wiki #REDIRECT [[The Boss]] 525eb3913da3d347e1fc98bce9e9581c9311dde1 Help 0 4 219 191 2012-10-21T18:34:06Z Zkiller 1253 /* Games */ wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena]] ** [[About us]] ** [[Club Board Game Arena]] ** [[Contact us]] === Detailed help === * [[Getting started]] * [[Referral]] * [[Browser support]] * [[Moderation and grades]] * [[Game clock]] * [[Rating]] * [[Reputation]] * [[Translation guidelines]] == Games == * [[Gamehelphaggis|Haggis]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelpdominion|Dominion]] * [[Gamehelpyearofthedragon|In the Year of the Dragon]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelptroyes|Troyes]] * [[Gamehelpgosu|Gosu]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelpamyitis|Amyitis]] * [[Gamehelptobago|Tobago]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpunclechesnutstablegype|Uncle Chesnut's Table Gype]] * [[Gamehelptheboss|The Boss]] c32d04b6feec5c8e94d0443e6936e954d3e3d428 Studio 0 49 220 2012-10-24T20:17:33Z Sourisdudesert 1 Created page with "'''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is opened to any gamer with development skills :) S..." wikitext text/x-wiki '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is opened to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 8bebe049b7e073dc301e36218d40bd9907ed708a 222 220 2012-10-24T20:24:57Z Sourisdudesert 1 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is opened to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 2b9e8a86566104378c88ee21ca98a6dac0bf5b5c 223 222 2012-10-24T20:33:05Z Sourisdudesert 1 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is opened to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How to develop a board game on BGA Studio? == At first, check out these presentations: == BGA Studio documentation == f9da3165f2dbc6f8331cbf2a9e4e2c321388d1d4 224 223 2012-10-24T20:40:16Z Sourisdudesert 1 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is opened to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How to develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] == BGA Studio documentation == e12da43129600f5b6278753f91665ff8dbfccc27 225 224 2012-10-24T20:42:01Z Sourisdudesert 1 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is opened to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How to develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * The 8 steps to create a board game on Board Game Arena == BGA Studio documentation == 5a9d214a8612c2563cbaad4cb5d70f3b7b7141b4 226 225 2012-10-24T20:52:50Z Sourisdudesert 1 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is opened to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How to develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] == BGA Studio documentation == (available soon...) 1bea11654a7ab6eb5b382657f96413c6797ba21e 228 226 2012-11-22T10:28:01Z Sourisdudesert 1 /* How to develop a board game on BGA Studio? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is opened to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How to develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == (available soon...) a51c138b49e90fc4c1382cfe9ce0daf64b17678c Restr:Bga studio small.jpg 6 50 221 2012-10-24T20:24:25Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Gamehelpintheyearofthedragon 0 51 227 2012-11-18T22:32:20Z Salty-horse 1046 Add end-of-round and -game scoring reminders wikitext text/x-wiki === End-of-round Scoring === * 1 point for each palace. * 1 point For each court lady. * 1 point For each privilege. (Small privilege = 1 point; Large privilege = 2 points) === End-of-game Scoring === * 2 points for each person tile. * For each monk: score [number of Buddhas] x [number of floors] points. * 1 point for each 3 yuan. 094e726d8bed26a5b54c43e6aa40764bda2b5679 Gamehelphearts 0 52 229 2012-11-22T12:36:19Z Daleb147 1803 Created page with "Hearts is a card game for 4 players, every man for himself. It uses the standard 52-card pack. '''Rank''' A (high) to 2 (low). '''Setup''' The entire deck is dealt, giving ..." wikitext text/x-wiki Hearts is a card game for 4 players, every man for himself. It uses the standard 52-card pack. '''Rank''' A (high) to 2 (low). '''Setup''' The entire deck is dealt, giving you a hand of 13 cards. After looking at your cards, choose to pass to another player. The passing rotation is: (1st hand) to the player on your left, (2nd hand) to the player on your right, (3rd hand) to the player across the table, (4th hand) no passing. The rotation repeats until the game ends. '''Tricks''' After passing cards, the player holding the 2 of clubs leads the first trick. Each player must follow suit if possible. If you have no cards of the suit led, you may play a card of any suit. Exception: You may not play a heart or the Queen of Spades on the first trick, even if you have no clubs. The highest card of the suit led wins the trick. The winner of a trick starts the next trick. Hearts may not be led until a heart has been played (this is called "breaking" hearts). The Queen of Spades may be lead at any time. [NB: In traditional Hearts, playing the Queen of Spades also breaks hearts.] There is no trump suit. '''Scoring''' At the end of each hand, each heart taken by a player counts -1, and the Queen of Spades counts -13. If one player has taken all 13 hearts ''and'' the Queen of Spades (this is known as shooting the moon), that player scores 0 and all other players score -26. When one or more players reach zero, the game ends. The player with the highest score wins. '''Variants''' Normal game is 100 points. Quick game is 75 points. c028cf9094219edf61eff451dedac653ab7fd8f2 230 229 2012-11-22T12:38:14Z Daleb147 1803 wikitext text/x-wiki Hearts is a card game for 4 players, every man for himself. It uses the standard 52-card pack. '''Rank''' A (high) to 2 (low). '''Setup''' The entire deck is dealt, giving you a hand of 13 cards. After looking at your cards, choose to pass to another player. The passing rotation is: (1st hand) to the player on your left, (2nd hand) to the player on your right, (3rd hand) to the player across the table, (4th hand) no passing. The rotation repeats until the game ends. '''Tricks''' After passing cards, the player holding the 2 of clubs leads the first trick. Each player must follow suit if possible. If you have no cards of the suit led, you may play a card of any suit. Exception: You may not play a heart or the Queen of Spades on the first trick, even if you have no clubs. The highest card of the suit led wins the trick. The winner of a trick starts the next trick. Hearts may not be led until a heart has been played (this is called "breaking" hearts). The Queen of Spades may be lead at any time. [NB: In traditional Hearts, playing the Queen of Spades also breaks hearts.] There is no trump suit. '''Scoring''' At the end of each hand, each heart taken by a player counts -1, and the Queen of Spades counts -13. If one player has taken all 13 hearts ''and'' the Queen of Spades (this is known as shooting the moon), that player scores 0 and all other players score -26. When one or more players reach zero, the game ends. The player with the highest score wins. '''Variants''' Normal game is 100 points. Quick game is 75 points. c8041d0b7782fad9106ef871a23dc9af7593637e 231 230 2012-11-22T12:39:33Z Daleb147 1803 wikitext text/x-wiki Hearts is a card game for 4 players, every man for himself. It uses the standard 52-card pack. '''Rank''' A (high) to 2 (low). '''Setup''' The entire deck is dealt, giving you a hand of 13 cards. After looking at your hand, choose three cards to pass to another player. The passing rotation is: (1st hand) to the player on your left, (2nd hand) to the player on your right, (3rd hand) to the player across the table, (4th hand) no passing. The rotation repeats until the game ends. '''Tricks''' After passing cards, the player holding the 2 of clubs leads the first trick. Each player must follow suit if possible. If you have no cards of the suit led, you may play a card of any suit. Exception: You may not play a heart or the Queen of Spades on the first trick, even if you have no clubs. The highest card of the suit led wins the trick. The winner of a trick starts the next trick. Hearts may not be led until a heart has been played (this is called "breaking" hearts). The Queen of Spades may be lead at any time. [NB: In traditional Hearts, playing the Queen of Spades also breaks hearts.] There is no trump suit. '''Scoring''' At the end of each hand, each heart taken by a player counts -1, and the Queen of Spades counts -13. If one player has taken all 13 hearts ''and'' the Queen of Spades (this is known as shooting the moon), that player scores 0 and all other players score -26. When one or more players reach zero, the game ends. The player with the highest score wins. '''Variants''' Normal game is 100 points. Quick game is 75 points. 24db4367246faacd715235883032541395f40c23 234 231 2012-11-22T23:25:47Z Daleb147 1803 wikitext text/x-wiki Hearts is a card game for 4 players, every man for himself. It uses the standard 52-card pack. '''Rank''' A (high) to 2 (low). '''Setup''' The entire deck is dealt, giving you a hand of 13 cards. After looking at your hand, choose three cards to pass to another player. The passing rotation is: (1st hand) to the player on your left, (2nd hand) to the player across the table, (3rd hand) to the player on your right, (4th hand) no passing. The rotation repeats until the game ends. '''Tricks''' After passing cards, the player holding the 2 of clubs leads the first trick. Each player must follow suit if possible. If you have no cards of the suit led, you may play a card of any suit. Exception: You may not play a heart or the Queen of Spades on the first trick, even if you have no clubs. The highest card of the suit led wins the trick. The winner of a trick starts the next trick. Hearts may not be led until a heart has been played (this is called "breaking" hearts). The Queen of Spades may be lead at any time. [NB: In traditional Hearts, playing the Queen of Spades also breaks hearts.] There is no trump suit. '''Scoring''' At the end of each hand, each heart taken by a player counts -1, and the Queen of Spades counts -13. If one player has taken all 13 hearts ''and'' the Queen of Spades (this is known as shooting the moon), that player scores 0 and all other players score -26. When one or more players reach zero, the game ends. The player with the highest score wins. '''Variants''' Normal game is 100 points. Quick game is 75 points. c134a170f6a54f64352aab39c6d476725b8c269f Development 0 47 232 190 2012-11-22T19:40:45Z Een 3 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is opened to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How to develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == (available soon...) a51c138b49e90fc4c1382cfe9ce0daf64b17678c 233 232 2012-11-22T19:43:23Z Een 3 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is opened to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How to develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === === What do I get? === === How should I start? === === Other ressources === FAQ Files reference Framework functions reference Development forum a26867be4e544f9a5579183b085ec9ad12fe79fe 235 233 2012-11-23T09:05:14Z Een 3 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is opened to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How to develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us|BGA contact address]. Please provide the following information: * developer's user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * developer's real name; * developer's email address; * developer's postal address. We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions document for developers on BGA Studio joined as an attachment. We also encourage you to tell us about which games you would love to develop on BGA! === Ok, I registered, what do I get? === First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! Then, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login and complex password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'ressources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initiated from our 'emptygame' template, providing the game structure (and comments! and examples!) Then you can start! === Great, I'm in! ... How should I start? === If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials). Then start editing files and see what happens! ;) === Other ressources === FAQ Files reference Framework functions reference Development forum bf764d6703bea2d63e7e6ca0e028982e48cd8292 236 235 2012-11-23T09:10:43Z Een 3 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * developer's user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * developer's real name; * developer's email address; * developer's postal address. We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions document for developers on BGA Studio joined as an attachment. We also encourage you to tell us about which games you would love to develop on BGA! === Ok, I registered, what do I get? === First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! Then, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login and complex password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'ressources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initiated from our 'emptygame' template, providing the game structure (and comments! and examples!) Then you can start! === Great, I'm in! ... How should I start? === If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials). Then start editing files and see what happens! ;) === Other ressources === [Development FAQ] [Development files reference] [Development framework functions reference] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 979e2f97593be050323fa3e481b8ba78467042da 237 236 2012-11-23T09:14:05Z Een 3 /* How do I register? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your contact e-mail address; * your postal address. We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! === Ok, I registered, what do I get? === First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! Then, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login and complex password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'ressources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initiated from our 'emptygame' template, providing the game structure (and comments! and examples!) Then you can start! === Great, I'm in! ... How should I start? === If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials). Then start editing files and see what happens! ;) === Other ressources === [Development FAQ] [Development files reference] [Development framework functions reference] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 72bf370daa09b9f048a4b31e1b98a5506fa633e6 238 237 2012-11-23T09:15:00Z Een 3 /* How do I register? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! === Ok, I registered, what do I get? === First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! Then, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login and complex password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'ressources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initiated from our 'emptygame' template, providing the game structure (and comments! and examples!) Then you can start! === Great, I'm in! ... How should I start? === If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials). Then start editing files and see what happens! ;) === Other ressources === [Development FAQ] [Development files reference] [Development framework functions reference] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] cf121fd0e36ab9d557973fb88647af87ee195063 239 238 2012-11-23T09:18:34Z Een 3 /* Ok, I registered, what do I get? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! === Ok, I registered, what do I get? === First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'ressources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! === Great, I'm in! ... How should I start? === If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials). Then start editing files and see what happens! ;) === Other ressources === [Development FAQ] [Development files reference] [Development framework functions reference] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] b6fda90a3132709481751181d2ce8aaff8f4862c 240 239 2012-11-23T09:21:31Z Een 3 /* Other ressources */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! === Ok, I registered, what do I get? === First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'ressources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! === Great, I'm in! ... How should I start? === If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials). Then start editing files and see what happens! ;) === Other ressources === [[Development FAQ]] [[Development files reference]] [[Development functions reference]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 2e858b45e252006334dcd72c76fca2988fe9cf4a 243 240 2012-11-23T09:52:04Z Een 3 /* Other ressources */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! === Ok, I registered, what do I get? === First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'ressources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! === Great, I'm in! ... How should I start? === If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials). Then start editing files and see what happens! ;) === Other resources === [[Development FAQ]] [[Development file reference]] [[Development function reference]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] e47246dabfa0a690d90e5b0629fd2cf3916767d5 248 243 2012-11-24T09:56:14Z Een 3 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! === Ok, I registered, what do I get? === First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'ressources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! === Great, I'm in! ... How should I start? === If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials). Then start editing files and see what happens! ;) === Other resources === [[Development FAQ]] [[Development file reference]] [[Development function reference]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 0c08a29e8f25782d85af7351110d1819061d46b3 Studio FAQ 0 53 241 2012-11-23T09:39:08Z Een 3 Created page with "This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Us..." wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == I updated the images in the 'img' folder of my game, but they don't show? == Please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. 245dd42acf9f030324bddb3016b307338c8f8fb1 242 241 2012-11-23T09:48:15Z Een 3 wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == I updated the images in the 'img' folder of my game, but they don't show? == Please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. b6678b288dddeacf8990a5fb7fb0afa71067c2fd Studio file reference 0 54 244 2012-11-23T10:53:17Z Een 3 Created page with " This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment. === 'img' directory === This direct..." wikitext text/x-wiki This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment. === 'img' directory === This directory contains the images for your game: * game_box.png is displayed on the main site on the game description page and when creating a table (280x280 px) * game_icon.png is the icon displayed in the lists of games and tables (50x50 px) * publisher.png is the logo of the publisher of the game, displayed on the game description page (width: 150 px) * and other images that you need. You should use [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites] for better web performance. === dbmodel.sql === File for creating specific database tables that you will need to persist data during the game (for example a table for cards). === gameoptions.inc.php === File for describing your game options (= game variants) === <gamename>.action.php === File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions. === <gamename>.css === CSS styles specific to your game. === <gamename>.game.php === This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. === <gamename>.js === This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. === <gamename>.view.php and <gamename>_<gamename>.tpl === Files used to set up the page layout ('view') for the game. === material.inc.php === File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants. === states.inc.php === This file describes the states your game will iterate over, and the transitions to get from one state to another. === stats.inc.php === File used to list statistics that you want to update during the game to be presented to players at the end of the game. bb690d4d6d5bf813de7ac7ae7d19ade7323cecab Studio function reference 0 55 245 2012-11-23T11:00:23Z Een 3 Created page with "This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to). == Server side (PHP functions) == ; todo ..." wikitext text/x-wiki This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to). == Server side (PHP functions) == ; todo : todo == Client side (Javascript functions) == ; todo : todo 533cc4280a0aee261ba9cca18e0a826f0de47487 Gamehelpdominion 0 29 246 76 2012-11-24T04:02:03Z Gelvo 1816 wikitext text/x-wiki '''Goal''' Be the player with the most victory points at the end of the game. '''Ending Condition''' The ''Province'' stack being depleted, or 3 stacks of cards being depleted. '''Setup''' Each player starts the game with a deck of 10 cards (3 ''Estates'', and 7 ''Copper''). The deck is shuffled and 5 cards are drawn to form the player's hand. '''Overview''' The A-B-C rule makes it easy to remember the play order. On a player's turn: A: Action: The player may play an action card. Each player is allowed 1 action per turn by default. Certain action cards provide additional actions. B: Buy: After the action phase is over, the player may play buy a card from the general supply. Bought cards are placed in the player's discard pile. Each player is allowed 1 buy per turn by default. Certain action cards provide additional buys. C: Cleanup: After the buy phase is over, the player places all cards (played cards and in hand cards) into the discard pile. Five new cards are drawn from the player's deck. If there aren't enough cards to form a full hand, the discard pile is reshuffled and forms the new deck. The game progresses in clockwise order until ending conditions are met. '''Tie-breaker''' If 2 or more players have the same number of victory points, the player that had the fewest number of turns wins. If there is still a tie, all tied players rejoice in a shared victory. '''Learning About Each Card''' To learn about each card in Dominion you can go to [http://deckengine.info/dominion/] 199dbbce7742bec95e581d7c67e7d3e6aafed394 247 246 2012-11-24T04:03:28Z Gelvo 1816 wikitext text/x-wiki '''Goal''' Be the player with the most victory points at the end of the game. '''Ending Condition''' The ''Province'' stack being depleted, or 3 stacks of cards being depleted. '''Setup''' Each player starts the game with a deck of 10 cards (3 ''Estates'', and 7 ''Copper''). The deck is shuffled and 5 cards are drawn to form the player's hand. '''Overview''' The A-B-C rule makes it easy to remember the play order. On a player's turn: A: Action: The player may play an action card. Each player is allowed 1 action per turn by default. Certain action cards provide additional actions. B: Buy: After the action phase is over, the player may play buy a card from the general supply. Bought cards are placed in the player's discard pile. Each player is allowed 1 buy per turn by default. Certain action cards provide additional buys. C: Cleanup: After the buy phase is over, the player places all cards (played cards and in hand cards) into the discard pile. Five new cards are drawn from the player's deck. If there aren't enough cards to form a full hand, the discard pile is reshuffled and forms the new deck. The game progresses in clockwise order until ending conditions are met. '''Tie-breaker''' If 2 or more players have the same number of victory points, the player that had the fewest number of turns wins. If there is still a tie, all tied players rejoice in a shared victory. '''Learning About Each Card''' To learn about each card in Dominion you can go to Deck Engine[http://deckengine.info/dominion/] d8bee17613455731e1204adcab26ce10795c6d0b Development 0 47 249 248 2012-11-24T11:08:45Z Een 3 /* Other resources */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! === Ok, I registered, what do I get? === First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'ressources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! === Great, I'm in! ... How should I start? === If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials). Then start editing files and see what happens! ;) === Other resources === [[Development FAQ]] [[Development file reference]] [[Development function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 2653ee87c6344ebf07629f0b3f8249b5f53ad234 250 249 2012-11-24T11:12:59Z Een 3 /* Ok, I registered, what do I get? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! === Ok, I registered, what do I get? === First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! === Great, I'm in! ... How should I start? === If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: (TODO: link tutorials). Then start editing files and see what happens! ;) === Other resources === [[Development FAQ]] [[Development file reference]] [[Development function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 6a298e378936e884914ef321723c403658e558f1 295 250 2012-11-24T17:46:44Z Een 3 /* Great, I'm in! ... How should I start? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick 'terms & conditions' document. It's really quick, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document (TODO: link pdf) as an attachment, and the sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! === Ok, I registered, what do I get? === First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! === Great, I'm in! ... How should I start? === If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: * [[Tutorial reversi]] * [[Tutorial hearts]] * [[Tutorial xxx ]] Then start editing files and see what happens! ;) === Other resources === [[Development FAQ]] [[Development file reference]] [[Development function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] eecf066a299c4dc0c3a8e68add20e2673f238869 Studio back-office 0 56 251 2012-11-24T11:38:02Z Een 3 Created page with "You will find the URL to the Studio back-office in the 'resources.html' file at the root of your SFTP access. Here is a list and description of the links and functions in thi..." wikitext text/x-wiki You will find the URL to the Studio back-office in the 'resources.html' file at the root of your SFTP access. Here is a list and description of the links and functions in this back-office. Click on a menu to display its content. === Documentation === Contains links to this wiki, the development forum and the bugs forum. === Database === Contains a link to the Studio database administration tool (PHPMyAdmin). Your login / password for this tool is the same as for your SFTP access. === Sources === Contains a form for committing your sources to the BGA repository. Game name field should contain the name of your game (lower case, no space). Comment should contain your commit comment describing changes to the code since your last commit. You should commit from time to time when you hit some landmarks in your development. This is an extra assurance not to lose your code, and to have the possibility (by asking us) to get a previous version of your code if you need to backtrack. === Logs === Gives you a web based access to the studio server logs. ; Current table error log : main log of interest to you while developing, it contains the error logs happening at the table you are currently playing at ; Current table request logs : this log traces all the actions happening at the table you are currently playing at ; Javascript error log : this log traces all the Javascript errors happening on the client side. Errors are also briefly displayed in your browser, but in this log it's better formatted and you can look a it quietly. ; Gameserver error log : this log traces all errors happening on the gameserver. It should mainly be useful if your game setup crashes (ie before your table is ready, so before errors are collected in the current table error log), for example if there is a syntax error in your 'dbmodel.sql' file. ; HTTP error log : this log traces the web server errors. This is useful to look at PHP syntax errors and warnings. Please note that the three last logs are common to all games being developed on the platform, so there may be some noise in the data you are interested in. You can open the log links in a different tab and just hit F5 when you need to refresh. The URL you will get for the new tab has a "?n=100" parameter that gives the number of lines to display: you can modify it in the URL if you need more. a75366b91b41d11f5f611dee233b0deee2fc46c7 252 251 2012-11-24T11:41:09Z Een 3 wikitext text/x-wiki You will find the URL to the Studio back-office in the 'resources.html' file at the root of your SFTP access. Here is a list and description of the links and functions in this back-office. Click on a menu to display its content. === Documentation === Contains links to this wiki, the development forum and the bugs forum. === Database === Contains a link to the Studio database administration tool (PHPMyAdmin). Your login / password for this tool is the same as for your SFTP access. === Sources === Contains a form for committing your sources to the BGA repository. * Game name field should contain the name of your game (lower case, no space). * Comment field should contain your commit comment describing changes to the code since your last commit. You should commit from time to time when you hit some landmarks in your development. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. === Logs === Gives you a web based access to the studio server logs. ; Current table error log : main log of interest to you while developing, it contains the error happening at the table you are currently playing at. ; Current table request logs : this log traces all the actions happening at the table you are currently playing at. ; Javascript error log : this log traces all the Javascript errors happening on the client side. Errors are also briefly displayed in your browser, but in this log it's better formatted and you can look a it quietly. ; Gameserver error log : this log traces all errors happening on the gameserver. It should mainly be useful if your game setup crashes (ie before your table is ready, so before errors are collected in the current table error log), for example if there is a syntax error in your 'dbmodel.sql' file. ; HTTP error log : this log traces the web server errors. This is useful to look at PHP syntax errors and warnings. Please note that the three last logs are common to all games being developed on the platform, so there may be some noise in the data you are interested in. You can open the log links in a different tab and just hit F5 when you need to refresh. The URL you will get for the new tab has a "?n=100" parameter that gives the number of lines to display: you can modify it in the URL if you need more. 5623b1560a6ae757eaa2f53c2494e6edda3eab19 Tutorial reversi 0 57 253 2012-11-24T13:03:49Z Sourisdudesert 1 Created page with "blabla" wikitext text/x-wiki blabla bb21158c733229347bd4e681891e213d94c685be 254 253 2012-11-24T13:09:13Z Sourisdudesert 1 wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. c26a5af8e6828564ab4ee223d229dc54a9b9286d 255 254 2012-11-24T13:14:14Z Sourisdudesert 1 wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == 1af09db09aef0c5098f0fa2a17b2ea9068a1de79 256 255 2012-11-24T13:15:59Z Sourisdudesert 1 wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. So, let's upload our board. f60e6e9884c37a2e73df5b02b3666c9caa1f5154 258 256 2012-11-24T13:27:24Z Sourisdudesert 1 /* Let it look like Reversi */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a <div> for your board <nowiki> <div id="board"> </div> </nowiki> 664e12899137864d7e95e67481c51c9a053b8da9 259 258 2012-11-24T13:33:03Z Sourisdudesert 1 wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <nowiki> <div id="board"> </div> </nowiki> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } b25c53195c653db74860f7375650536de492b023 261 259 2012-11-24T13:34:55Z Sourisdudesert 1 wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <nowiki> <div id="board"> </div> </nowiki> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] 8bdac21920f65576aeff896481ae1b41e77998bf 262 261 2012-11-24T13:41:58Z Sourisdudesert 1 wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> 2aa9b4055aa2b3b3bd8d72e989c3c0d2d8bf7541 263 262 2012-11-24T13:49:19Z Sourisdudesert 1 /* Make the squares appears */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. e8f724d68a8ff40cf5c1e30ee29a194a91df7e95 264 263 2012-11-24T13:50:24Z Sourisdudesert 1 /* Make the squares appears */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] 9f506bb9b9388809e70f528325323a3ea3820bdc 267 264 2012-11-24T13:57:41Z Sourisdudesert 1 wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Then, let's design some white&black disc tokens with a little bit of CSS d6c98d457f8c2baf69ddcb3ea2de8566b739ac7d 269 267 2012-11-24T14:00:05Z Sourisdudesert 1 /* The discs */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Then, let's design some white&black disc tokens with a little bit of CSS 45d86a617f0bcaabd8a2a2e713ff1ddf0d7b6828 270 269 2012-11-24T14:05:02Z Sourisdudesert 1 /* The discs */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "javascript template". aea59cd9a0d5a655a1bfc40de5928cb39c07cd42 271 270 2012-11-24T14:15:06Z Sourisdudesert 1 /* The discs */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. 61619f1af84c80d04243ea001a6082b77b3e6dac 272 271 2012-11-24T14:18:04Z Sourisdudesert 1 /* The discs */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] f476c6f09986a1589113b80bcde9b224e8b37e07 274 272 2012-11-24T14:22:59Z Sourisdudesert 1 /* The discs */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Note: of course we can't explain how d9c8d7a3f87db8034e553a1b158b1bdf75e7e4ea 275 274 2012-11-24T14:23:39Z Sourisdudesert 1 /* Introduction */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Note: of course we can't explain how 109fc90a2a4ccc1e28bfec0b718896f72258b878 276 275 2012-11-24T14:30:01Z Sourisdudesert 1 /* The database */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. == Setup the initial game position == Initially, there are 4 tokens on the board (2 white, 2 black). f3bd28bcc75748f33ef11ca30faa653345b6eba5 277 276 2012-11-24T14:38:27Z Sourisdudesert 1 /* Setup the initial game position */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. 5bd54f607111d419b76ae50aad1bee09b1fce065 278 277 2012-11-24T14:40:11Z Sourisdudesert 1 /* The database */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. 3740876f658f944737528e641e6352ddff6c27f6 280 278 2012-11-24T14:41:02Z Sourisdudesert 1 /* Setup the initial game position */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] 3baeffb6a7a725930a2c768e195a2650f5ae7750 282 280 2012-11-24T14:42:23Z Sourisdudesert 1 /* Setup the initial game position */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... b54d251dbf8e412c8a606c3625258999a7a14611 283 282 2012-11-24T14:43:09Z Sourisdudesert 1 /* The database */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... be60f242a3d7610172e71f72d90cdbd0119508ec 284 283 2012-11-24T14:47:37Z Sourisdudesert 1 /* Setup the initial game position */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] 26605e3dcebc2d859057134f2e4a955b9f084d7f 286 284 2012-11-24T14:49:10Z Sourisdudesert 1 /* The game state machine */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> 7f239e145406ed06bd3d5ea48e7abc90f39f58ee 287 286 2012-11-24T14:52:34Z Sourisdudesert 1 /* The game state machine */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture above, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] 45143c8f884d71113786b746e717385e427b1680 289 287 2012-11-24T15:07:07Z Sourisdudesert 1 /* The game state machine */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture above, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. 1d617cd8cd2e69715ffa9220f5d7e7c3070aadbc 290 289 2012-11-24T15:10:37Z Sourisdudesert 1 /* The rules */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture above, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed move == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above: 3c3e0f3dbdd3a75eea3c82143585d5912b6d1a4e 291 290 2012-11-24T15:10:55Z Sourisdudesert 1 /* The game state machine */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed move == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above: ebc5c345f749b004365eda4eef51ebbafd90d7c9 292 291 2012-11-24T15:18:41Z Sourisdudesert 1 /* Display allowed move */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it. At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] 1e8642b57da1bb69f6b242f3f05230046dbc9404 294 292 2012-11-24T15:30:07Z Sourisdudesert 1 /* Display allowed moves */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it. At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. 84b70487a17c62e442649e14de5f32556560912f 297 294 2012-11-25T10:24:14Z Sourisdudesert 1 /* Let's play */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it. At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> </pre> </pre> fd595cb9caea45c80ef81cdcf140310731e6d701 298 297 2012-11-25T10:30:46Z Sourisdudesert 1 /* Let's play */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it. At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). Now 64278699265cc34b9bc9f92c7be45317d9301059 Restr:Board.jpg 6 58 257 2012-11-24T13:16:48Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Reversi1.jpg 6 59 260 2012-11-24T13:34:17Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Reversi2.jpg 6 60 265 2012-11-24T13:50:36Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 266 265 2012-11-24T13:50:59Z Sourisdudesert 1 uploaded a new version of &quot;[[File:Reversi2.jpg]]&quot; wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Tokens.png 6 61 268 2012-11-24T13:58:04Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Reversi3.jpg 6 62 273 2012-11-24T14:18:16Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Reversi4.jpg 6 63 279 2012-11-24T14:40:25Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Reversi5.jpg 6 64 281 2012-11-24T14:41:52Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Reversi6.jpg 6 65 285 2012-11-24T14:47:49Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Reversi7.jpg 6 66 288 2012-11-24T14:53:29Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Reversi8.jpg.jpg 6 67 293 2012-11-24T15:18:51Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Studio FAQ 0 53 296 242 2012-11-24T18:17:21Z Een 3 wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == I updated the images in the 'img' folder of my game, but they don't show? == Please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "go to database" link at the bottom of your game. This link will bring you directly to the database for the current table. c077ff8abbf540a10b8cb8c5557634d59d5d85ff Tutorial reversi 0 57 299 298 2012-11-25T10:34:51Z Sourisdudesert 1 /* Let's play */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it. At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state: <pre> function stNextPlayer() { // Active next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appear in the database: [[File:reversi9.jpg]] 6101cdabac21b0201d459cc1468064208a53397e 301 299 2012-11-25T10:37:05Z Sourisdudesert 1 /* Let's play */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it. At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state: <pre> function stNextPlayer() { // Active next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appears automatically == 4cd2519b3e4199201ca4dcc3b691f5ca772579af 322 301 2012-11-28T16:39:13Z Sourisdudesert 1 /* Make the move appears automatically */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it. At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state: <pre> function stNextPlayer() { // Active next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appears automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handle the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Made these discs blinking and set them to the specified color for( var i in notif.args.turnedOver ) { var disc = notif.args.turnedOver[ i ]; // Make the disc blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'disccolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> 03d8de1fa331667d24bce827ab6b49abd375f329 323 322 2012-11-28T16:43:41Z Sourisdudesert 1 /* Make the move appears automatically */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on BGA environment: Reversi game. Before reading this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It is always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful during designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, then faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements when squares are. These elements will be used as position references for width&black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, is we apply the classes "token" and "tokencolor_ffffff" to a div element, we got a white token. Yeah. Note the "position: absolute" which allow us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appears on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it. At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state: <pre> function stNextPlayer() { // Active next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appears automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handle the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Made these discs blinking and set them to the specified color for( var i in notif.args.turnedOver ) { var disc = notif.args.turnedOver[ i ]; // Make the disc blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'disccolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". d69108e07a1157d677d0be32ad3ad5f0bf653860 Restr:Reversi9.jpg 6 68 300 2012-11-25T10:35:06Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Studio FAQ 0 53 302 296 2012-11-25T12:38:59Z Een 3 /* Is there a quick way to access the database for my current table? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == I updated the images in the 'img' folder of my game, but they don't show? == Please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. d08951d5aeff9840f161e2f42c60814d94b4a982 314 302 2012-11-27T20:52:20Z Een 3 moved [[Development FAQ]] to [[Studio FAQ]] wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == I updated the images in the 'img' folder of my game, but they don't show? == Please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. d08951d5aeff9840f161e2f42c60814d94b4a982 329 314 2012-11-30T13:13:17Z Een 3 wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ) In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == Please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. e6503c44ae66f7402062c4967deadea42a478c0e 330 329 2012-11-30T13:13:43Z Een 3 /* Is there a special way to declare the strings that must be translated? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == Please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. 347ddc92e9e7cbfe28522592fc2550230373ab27 345 330 2012-12-05T19:50:05Z Een 3 /* I updated the images in the 'img' folder of my game, but they don't show? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that serves to launch the games. The game icon, box and the publisher logo are hosted on the mainsite server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the Studio back office to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. 4b25daf1b81ba2f65df3a679e295cb84e26d2a09 346 345 2012-12-05T19:59:56Z Een 3 wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that serves to launch the games. The game icon, box and the publisher logo are hosted on the mainsite server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. 639042654b8518f33cb968566c4b2a10df9ada31 347 346 2012-12-05T20:01:10Z Een 3 /* I updated the images in the 'img' folder of my game, but they don't show? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. c08c1dd70f4dc43128232e20b3f7bb9a1a4e9644 Development 0 47 303 295 2012-11-25T16:46:42Z Een 3 /* How do I register? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [['terms & conditions' document:BGA_TC_Dev_en.pdf]]. It's really quick, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment and the following sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! === Ok, I registered, what do I get? === First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! === Great, I'm in! ... How should I start? === If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: * [[Tutorial reversi]] * [[Tutorial hearts]] * [[Tutorial xxx ]] Then start editing files and see what happens! ;) === Other resources === [[Development FAQ]] [[Development file reference]] [[Development function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] ea9b6c9329378a3c6087764ef21789fa4045658c 310 303 2012-11-25T21:20:30Z Een 3 /* How do I register? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment and the following sentence 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! === Ok, I registered, what do I get? === First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! === Great, I'm in! ... How should I start? === If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: * [[Tutorial reversi]] * [[Tutorial hearts]] * [[Tutorial xxx ]] Then start editing files and see what happens! ;) === Other resources === [[Development FAQ]] [[Development file reference]] [[Development function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 250ad0fb0beb3717c7ba8e705c8e07a5af724385 311 310 2012-11-25T21:22:25Z Een 3 /* How do I register? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! === Ok, I registered, what do I get? === First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! === Great, I'm in! ... How should I start? === If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: * [[Tutorial reversi]] * [[Tutorial hearts]] * [[Tutorial xxx ]] Then start editing files and see what happens! ;) === Other resources === [[Development FAQ]] [[Development file reference]] [[Development function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 5af77415355ccf88e63dafcfd73ca902364ca78d 316 311 2012-11-27T20:53:07Z Een 3 /* Other resources */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == BGA Studio documentation == === How do I register? === Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! === Ok, I registered, what do I get? === First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! === Great, I'm in! ... How should I start? === If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: * [[Tutorial reversi]] * [[Tutorial hearts]] * [[Tutorial xxx ]] Then start editing files and see what happens! ;) === Other resources === [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] c025722f9ad5f6199ddad7cb28099f0eeee36959 321 316 2012-11-27T20:54:33Z Een 3 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == How do I register? == Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek to tutorials for the example games: * [[Tutorial reversi]] * [[Tutorial hearts]] * [[Tutorial xxx ]] Then start editing files and see what happens! ;) == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] cd840ccedee7bdbbb48175292cdbc187adffda9e 328 321 2012-11-29T23:08:13Z Een 3 /* Great, I'm in! ... How should I start? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == How do I register? == Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at tutorials for two example games: * [[Tutorial reversi]] * [[Tutorial gomoku ]] Then start editing files and see what happens! ;) == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 2d04ceb441b20e7d1be485478ad8716df8f72b6a 332 328 2012-11-30T13:50:28Z Een 3 /* How can I develop a board game on BGA Studio? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at tutorials for two example games: * [[Tutorial reversi]] * [[Tutorial gomoku ]] Then start editing files and see what happens! ;) == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 39257b26b818eda07805de2338e456c3b42df777 333 332 2012-11-30T13:54:00Z Een 3 /* Great, I'm in! ... How should I start? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at this tutorial for the Reversi example game: * [[Tutorial reversi]] Then start editing files and see what happens! ;) == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 5f43c2d8a01bca25cac35caa417c67c5428ecf07 334 333 2012-11-30T13:54:35Z Een 3 /* Great, I'm in! ... How should I start? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail to [http://en.boardgamearena.com/#!doc/Contact_us BGA contact address]. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at this tutorial for creating the Reversi example game: * [[Tutorial reversi]] Then start editing files and see what happens! ;) == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 72dc57200d6a3312dadb9ff5d2d1aaa7c3d73e0e 336 334 2012-11-30T14:35:09Z Een 3 /* How do I register? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail to studio(at)boardgamearena.com. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at this tutorial for creating the Reversi example game: * [[Tutorial reversi]] Then start editing files and see what happens! ;) == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 7bd6cd9d30a6adb2837daf46206634e2e087c3cb 337 336 2012-11-30T14:35:27Z Een 3 /* How do I register? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail at studio(at)boardgamearena.com. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at this tutorial for creating the Reversi example game: * [[Tutorial reversi]] Then start editing files and see what happens! ;) == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 4bd37a3234a5ff6846a7e6a0a266ea4d532a6874 338 337 2012-11-30T14:35:54Z Een 3 /* How do I register? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, you get by e-mail a list of the games we have an agreement to develop. Please keep this list confidential, or it would ruin our tradition to make players guess the name of the next game on the forum! <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at this tutorial for creating the Reversi example game: * [[Tutorial reversi]] Then start editing files and see what happens! ;) == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 0460b4756dc697bb7e2c0313c08d9d41e4365a2b 339 338 2012-11-30T14:57:01Z Een 3 /* Ok, I registered, what do I get? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum!) <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at this tutorial for creating the Reversi example game: * [[Tutorial reversi]] Then start editing files and see what happens! ;) == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] ec37ab7db579bad08c6bd4b2d8944c42f8289445 340 339 2012-11-30T14:57:41Z Een 3 /* Ok, I registered, what do I get? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum) <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at this tutorial for creating the Reversi example game: * [[Tutorial reversi]] Then start editing files and see what happens! ;) == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 9ed07dc33eb79a958736a93bf3dc10151ecdd400 341 340 2012-11-30T15:03:35Z Een 3 /* Great, I'm in! ... How should I start? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum) <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at this tutorial for creating the Reversi example game: * [[Tutorial reversi]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]! == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] d2385456525acba6606d1944f34d9bac47a0460a 342 341 2012-11-30T15:03:57Z Een 3 /* Great, I'm in! ... How should I start? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum) <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at this tutorial for creating the Reversi example game: * [[Tutorial reversi]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 01f7f2a589a553ea6267d12e68f7b0cd5907a607 344 342 2012-11-30T15:50:47Z Een 3 Redirected page to [[Studio]] wikitext text/x-wiki #REDIRECT[[Studio]] 75f930ede7d4ad1a62943418c718a02b755fc4d5 Studio function reference 0 55 304 245 2012-11-25T18:37:20Z Een 3 wikitext text/x-wiki This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to). == Server side (PHP functions) == === APP_GameAction class <gamename>.action.php === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false ) : Get script argument with the correct type : bCanFail means than a validation failure is possible (user input) : The main argType values are as follows. <pre> define( 'AT_int', 0 ); // an integer define( 'AT_posint', 1 ); // a positive integer define( 'AT_float', 2 ); // a float define( 'AT_email', 3 ); // an email define( 'AT_url', 4 ); // a URL define( 'AT_bool', 5 ); // 1/0/true/false define( 'AT_enum', 6 ); // argTypeDetails list the possible values define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space </pre> === Table class (<gamename>.game.php) === == Client side (Javascript functions) == ; todo : todo 5a8d76a6197493599d8d3a89cb9447ed0edc7c2b 305 304 2012-11-25T18:57:56Z Een 3 wikitext text/x-wiki This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to). == Server side (PHP functions) == === APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false ) : Get script argument with the correct type : bCanFail means than a validation failure is possible (user input) : The main argType values are as follows. <pre> define( 'AT_int', 0 ); // an integer define( 'AT_posint', 1 ); // a positive integer define( 'AT_float', 2 ); // a float define( 'AT_email', 3 ); // an email define( 'AT_url', 4 ); // a URL define( 'AT_bool', 5 ); // 1/0/true/false define( 'AT_enum', 6 ); // argTypeDetails list the possible values define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space </pre> === Table class (<gamename>.game.php) === ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value ; function DbQuery( $sql ) : Executes sql query on the database ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty. ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found : Raise an exception if more than 1 row is returned ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row == Client side (Javascript functions) == ; todo : todo c8e9bb737a440acb0eee50a8b34aa14ef8a13edb 306 305 2012-11-25T19:04:06Z Een 3 /* Table class (.game.php) */ wikitext text/x-wiki This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to). == Server side (PHP functions) == === APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false ) : Get script argument with the correct type : bCanFail means than a validation failure is possible (user input) : The main argType values are as follows. <pre> define( 'AT_int', 0 ); // an integer define( 'AT_posint', 1 ); // a positive integer define( 'AT_float', 2 ); // a float define( 'AT_email', 3 ); // an email define( 'AT_url', 4 ); // a URL define( 'AT_bool', 5 ); // 1/0/true/false define( 'AT_enum', 6 ); // argTypeDetails list the possible values define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space </pre> === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value ; function DbQuery( $sql ) : Executes sql query on the database ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty. ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found : Raise an exception if more than 1 row is returned ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row == Client side (Javascript functions) == ; todo : todo 0b01bb492d9f22816dcd327e0def11a3e8abe281 307 306 2012-11-25T19:15:02Z Een 3 wikitext text/x-wiki This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to). == Server side (PHP functions) == === APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false ) : Get script argument with the correct type : bCanFail means than a validation failure is possible (user input) : The main argType values are as follows. <pre> define( 'AT_int', 0 ); // an integer define( 'AT_posint', 1 ); // a positive integer define( 'AT_float', 2 ); // a float define( 'AT_email', 3 ); // an email define( 'AT_url', 4 ); // a URL define( 'AT_bool', 5 ); // 1/0/true/false define( 'AT_enum', 6 ); // argTypeDetails list the possible values define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space </pre> === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value ; function DbQuery( $sql ) : Executes sql query on the database ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty. ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found : Raise an exception if more than 1 row is returned ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. == Client side (Javascript functions) == ; todo : todo 64a5654f4a93ed215c0270c01cde118163a7664a 308 307 2012-11-25T21:10:34Z Een 3 /* Client side (Javascript functions) */ wikitext text/x-wiki This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to). == Server side (PHP functions) == === APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false ) : Get script argument with the correct type : bCanFail means than a validation failure is possible (user input) : The main argType values are as follows. <pre> define( 'AT_int', 0 ); // an integer define( 'AT_posint', 1 ); // a positive integer define( 'AT_float', 2 ); // a float define( 'AT_email', 3 ); // an email define( 'AT_url', 4 ); // a URL define( 'AT_bool', 5 ); // 1/0/true/false define( 'AT_enum', 6 ); // argTypeDetails list the possible values define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space </pre> === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value ; function DbQuery( $sql ) : Executes sql query on the database ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty. ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found : Raise an exception if more than 1 row is returned ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. == Client side (Javascript functions) == ; this.slideToObjectPos( $('token_'+token.token_id), $('cp_background'), x_pix, y_pix, 10 ).play(); ; this.isSpectator ; this.player_id ; this.updateCounters(gamedatas.counters) ; this.addTooltipToClass( 'cp_token_icon_color1', _('Green'), '' ); ; this.addEventToClass( "cp_token", "onclick", "onClickToken"); ; this.isCurrentPlayerActive() ; this.checkAction( 'selectTokens' ) ; this.showMessage( _('You must select at least two tokens'), 'error' ); ; this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); ; this.updateCounters(notif.args.counters); ; this.ajaxcall( "/colorpop/colorpop/endgame.html", { }, this, function( result ) {} ); b8930b0747d4b187b304b90ae7bc63c4996b456f 317 308 2012-11-27T20:53:20Z Een 3 moved [[Development function reference]] to [[Studio function reference]] wikitext text/x-wiki This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to). == Server side (PHP functions) == === APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false ) : Get script argument with the correct type : bCanFail means than a validation failure is possible (user input) : The main argType values are as follows. <pre> define( 'AT_int', 0 ); // an integer define( 'AT_posint', 1 ); // a positive integer define( 'AT_float', 2 ); // a float define( 'AT_email', 3 ); // an email define( 'AT_url', 4 ); // a URL define( 'AT_bool', 5 ); // 1/0/true/false define( 'AT_enum', 6 ); // argTypeDetails list the possible values define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space </pre> === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value ; function DbQuery( $sql ) : Executes sql query on the database ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty. ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found : Raise an exception if more than 1 row is returned ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. == Client side (Javascript functions) == ; this.slideToObjectPos( $('token_'+token.token_id), $('cp_background'), x_pix, y_pix, 10 ).play(); ; this.isSpectator ; this.player_id ; this.updateCounters(gamedatas.counters) ; this.addTooltipToClass( 'cp_token_icon_color1', _('Green'), '' ); ; this.addEventToClass( "cp_token", "onclick", "onClickToken"); ; this.isCurrentPlayerActive() ; this.checkAction( 'selectTokens' ) ; this.showMessage( _('You must select at least two tokens'), 'error' ); ; this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); ; this.updateCounters(notif.args.counters); ; this.ajaxcall( "/colorpop/colorpop/endgame.html", { }, this, function( result ) {} ); b8930b0747d4b187b304b90ae7bc63c4996b456f 324 317 2012-11-29T22:47:37Z Een 3 /* Client side (Javascript functions) */ wikitext text/x-wiki This page references useful server side and client side functions, so that nobody needs to reinvent the wheel (unless he wants to). == Server side (PHP functions) == === APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false ) : Get script argument with the correct type : bCanFail means than a validation failure is possible (user input) : The main argType values are as follows. <pre> define( 'AT_int', 0 ); // an integer define( 'AT_posint', 1 ); // a positive integer define( 'AT_float', 2 ); // a float define( 'AT_email', 3 ); // an email define( 'AT_url', 4 ); // a URL define( 'AT_bool', 5 ); // 1/0/true/false define( 'AT_enum', 6 ); // argTypeDetails list the possible values define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space </pre> === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value ; function DbQuery( $sql ) : Executes sql query on the database ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty. ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found : Raise an exception if more than 1 row is returned ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. == Client side (Javascript functions) == ; this.player_id : Id of the player on which browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). ; 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; this.addEventToClass( "cp_token", "onclick", "onClickToken"); ; this.isCurrentPlayerActive() ; this.checkAction( 'selectTokens' ) ; this.showMessage( _('You must select at least two tokens'), 'error' ); ; this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); ; this.updateCounters(notif.args.counters); ; this.ajaxcall( "/colorpop/colorpop/endgame.html", { }, this, function( result ) {} ); 2883f9c0abb0ad4818ba23199536621e31463a82 325 324 2012-11-29T23:04:27Z Een 3 wikitext text/x-wiki This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to). == Server side (PHP functions) == === APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false ) : Get script argument with the correct type : bCanFail means than a validation failure is possible (user input) : The main argType values are as follows. <pre> define( 'AT_int', 0 ); // an integer define( 'AT_posint', 1 ); // a positive integer define( 'AT_float', 2 ); // a float define( 'AT_email', 3 ); // an email define( 'AT_url', 4 ); // a URL define( 'AT_bool', 5 ); // 1/0/true/false define( 'AT_enum', 6 ); // argTypeDetails list the possible values define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space </pre> === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value ; function DbQuery( $sql ) : Executes sql query on the database ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty. ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found : Raise an exception if more than 1 row is returned ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. == Client side (Javascript functions) == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). ; 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 196b47f3b6d139d77a359829cbfa749061bc3d73 326 325 2012-11-29T23:06:57Z Een 3 wikitext text/x-wiki This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to). This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below. == Server side (PHP functions) == === APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false ) : Get script argument with the correct type : bCanFail means than a validation failure is possible (user input) : The main argType values are as follows. <pre> define( 'AT_int', 0 ); // an integer define( 'AT_posint', 1 ); // a positive integer define( 'AT_float', 2 ); // a float define( 'AT_email', 3 ); // an email define( 'AT_url', 4 ); // a URL define( 'AT_bool', 5 ); // 1/0/true/false define( 'AT_enum', 6 ); // argTypeDetails list the possible values define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space </pre> === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value ; function DbQuery( $sql ) : Executes sql query on the database ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty. ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found : Raise an exception if more than 1 row is returned ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. == Client side (Javascript functions) == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). ; 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 3cbe8ea5ebf585d8ace0752c8030f718dd2fe28b 327 326 2012-11-29T23:07:06Z Een 3 wikitext text/x-wiki This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to). This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below. == Server side (PHP functions) == === APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false ) : Get script argument with the correct type : bCanFail means than a validation failure is possible (user input) : The main argType values are as follows. <pre> define( 'AT_int', 0 ); // an integer define( 'AT_posint', 1 ); // a positive integer define( 'AT_float', 2 ); // a float define( 'AT_email', 3 ); // an email define( 'AT_url', 4 ); // a URL define( 'AT_bool', 5 ); // 1/0/true/false define( 'AT_enum', 6 ); // argTypeDetails list the possible values define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space </pre> === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value ; function DbQuery( $sql ) : Executes sql query on the database ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty. ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found : Raise an exception if more than 1 row is returned ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. == Client side (Javascript functions) == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). ; 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 55c96307b77bd59db8d1da2247aa971adf57c54a Restr:BGA TC Dev en.pdf 6 69 309 2012-11-25T21:17:46Z Een 3 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 331 309 2012-11-30T13:33:17Z Een 3 uploaded a new version of &quot;[[File:BGA TC Dev en.pdf]]&quot; wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Studio back-office 0 56 312 252 2012-11-27T20:50:47Z Een 3 wikitext text/x-wiki You will find the URL to the Studio back-office in the 'resources.html' file at the root of your SFTP access. Here is a list and description of the links and functions in this back-office. Click on a menu to display its content. === Documentation === Contains links to this wiki, the development forum and the bugs forum. === Database === Contains a link to the Studio database administration tool (PHPMyAdmin). Your login / password for this tool is the same as for your SFTP access. === Sources === Contains a form for committing your sources to the BGA repository. * Game name field should contain the name of your game (lower case, no space). * Comment field should contain your commit comment describing changes to the code since your last commit. You should commit from time to time when you hit some landmarks in your development. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. === Logs === Gives you a web based access to the studio server logs. ; Current table error log : main log of interest to you while developing, it contains the error happening at the table you are currently playing at. ; Current table request logs : this log traces all the actions happening at the table you are currently playing at. ; Javascript error log : this log traces all the Javascript errors happening on the client side. Errors are also briefly displayed in your browser, but in this log it's better formatted and you can look a it quietly. ; Gameserver error log : this log traces all errors happening on the gameserver. It should mainly be useful if your game setup crashes (ie before your table is ready, so before errors are collected in the current table error log), for example if there is a syntax error in your 'dbmodel.sql' file. ; HTTP error log : this log traces the web server errors. This is useful to look at PHP syntax errors and warnings. Please note that the three last logs are common to all games being developed on the platform, so there may be some noise in the data you are interested in. You can open the log links in a different tab and just hit F5 when you need to refresh. The URL you will get for the new tab has a "?n=100" parameter that gives the number of lines to display: you can modify it in the URL if you need more. b8dac291fbe5b8e2412fc015dff9c7f432d8bd59 313 312 2012-11-27T20:51:22Z Een 3 wikitext text/x-wiki You will find the URL to the Studio back-office in the 'resources.html' file at the root of your SFTP access. Here is a list and description of the links and functions in this back-office. Click on a menu to display its content. === Documentation === Contains links to this wiki, the development forum and the bugs forum. === Database === Contains a link to the Studio database administration tool (PHPMyAdmin). Your login / password for this tool is the same as for your SFTP access. === Sources === Contains a form for committing your sources to the BGA repository. * Game name field should contain the name of your game (lower case, no space). * Comment field should contain your commit comment describing changes to the code since your last commit. You should commit from time to time when you hit some landmarks in your development. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. === Logs === Gives you a web based access to the studio server logs. ; Current table error log : main log of interest to you while developing, it contains the error happening at the table you are currently playing at. ; Current table request logs : this log traces all the actions happening at the table you are currently playing at. ; Javascript error log : this log traces all the Javascript errors happening on the client side. Errors are also briefly displayed in your browser, but in this log it's better formatted and you can look a it quietly. ; Gameserver error log : this log traces all errors happening on the gameserver. It should mainly be useful if your game setup crashes (ie before your table is ready, so before errors are collected in the current table error log), for example if there is a syntax error in your 'dbmodel.sql' file. ; HTTP error log : this log traces the web server errors. This is useful to look at PHP syntax errors and warnings. Please note that the three last logs are common to all games being developed on the platform, so there may be some noise in the data you are interested in. You can open the log links in a different tab and just hit F5 when you need to refresh. The URL you will get for the new tab has a "?n=100" parameter that gives the number of lines to display: you can modify it in the URL if you need more. cdb10c7884bbf321c65a6abd52427eee6870b1b3 Development FAQ 0 70 315 2012-11-27T20:52:20Z Een 3 moved [[Development FAQ]] to [[Studio FAQ]] wikitext text/x-wiki #REDIRECT [[Studio FAQ]] 0e0d928fd9ebb07aa5cabcbcb800036357516c70 Development function reference 0 71 318 2012-11-27T20:53:20Z Een 3 moved [[Development function reference]] to [[Studio function reference]] wikitext text/x-wiki #REDIRECT [[Studio function reference]] 0d4e31ae78128f335e8e652b8bd209497bea7540 Studio file reference 0 54 319 244 2012-11-27T20:53:33Z Een 3 moved [[Development file reference]] to [[Studio file reference]] wikitext text/x-wiki This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment. === 'img' directory === This directory contains the images for your game: * game_box.png is displayed on the main site on the game description page and when creating a table (280x280 px) * game_icon.png is the icon displayed in the lists of games and tables (50x50 px) * publisher.png is the logo of the publisher of the game, displayed on the game description page (width: 150 px) * and other images that you need. You should use [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites] for better web performance. === dbmodel.sql === File for creating specific database tables that you will need to persist data during the game (for example a table for cards). === gameoptions.inc.php === File for describing your game options (= game variants) === <gamename>.action.php === File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions. === <gamename>.css === CSS styles specific to your game. === <gamename>.game.php === This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. === <gamename>.js === This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. === <gamename>.view.php and <gamename>_<gamename>.tpl === Files used to set up the page layout ('view') for the game. === material.inc.php === File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants. === states.inc.php === This file describes the states your game will iterate over, and the transitions to get from one state to another. === stats.inc.php === File used to list statistics that you want to update during the game to be presented to players at the end of the game. bb690d4d6d5bf813de7ac7ae7d19ade7323cecab Development file reference 0 72 320 2012-11-27T20:53:33Z Een 3 moved [[Development file reference]] to [[Studio file reference]] wikitext text/x-wiki #REDIRECT [[Studio file reference]] 7e0b4170c41b68fcf9b09724d3d1b7bf8de5a76e Tutorial gomoku 0 73 335 2012-11-30T13:56:04Z Een 3 Created page with "TODO" wikitext text/x-wiki TODO b698c11e84460ed5999bfeb5cbf25b865c238f3c Studio 0 49 343 228 2012-11-30T15:49:04Z Een 3 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum) <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at this tutorial for creating the Reversi example game: * [[Tutorial reversi]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 01f7f2a589a553ea6267d12e68f7b0cd5907a607 Restr:Gomoku tuto1.png 6 74 348 2012-12-05T21:06:58Z Een 3 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Gomoku tuto2.png 6 75 349 2012-12-05T21:07:10Z Een 3 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Gomoku tuto3.png 6 76 350 2012-12-05T21:07:19Z Een 3 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Gomoku tuto4.png 6 77 351 2012-12-05T21:07:29Z Een 3 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Gomoku tuto5.png 6 78 352 2012-12-05T21:07:38Z Een 3 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Gomoku tuto6.png 6 79 353 2012-12-05T21:07:49Z Een 3 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Tutorial gomoku 0 73 354 335 2012-12-05T21:09:23Z Een 3 wikitext text/x-wiki Here is how your games look by default when it has just been created : [[File:Gomoku tuto1.png]] Gather useful images for the game and edit them as needed. Edit .tpl & .css to add the board : [[File:Gomoku tuto2.png]] Edit .sql to create a table for intersections. Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database. Edit .game.php->getAllDatas to retrieve the state of the intersections from the database. Edit .tpl to create a template for intersections (jstpl_intersection). Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning. [[File:Gomoku tuto3.png]] Define your game states in states.inc.php Add onclick events on intersections in .js, calling an action with appropriate parameters Add action in .action.php, retrieving parameters and calling the appropriate game action. Add game action in .game.php to update the database, then notify the client using a method ‘’ Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. The basic game turn is implemented: you can drop some stones. [[File:Gomoku tuto4.png]] Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] Implement specific rules for the game (if any) Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js Test everything thoroughly... you are done! [[File:Gomoku tuto6.png]] fcf0d63e99019e009a64cc2f45a3061e0997cdd4 355 354 2012-12-05T21:14:00Z Een 3 wikitext text/x-wiki == Start from the emtpy game template == Here is how your games look by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Edit .tpl & .css to add the board : [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit .sql to create a table for intersections. Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database. Edit .game.php->getAllDatas to retrieve the state of the intersections from the database. Edit .tpl to create a template for intersections (jstpl_intersection). Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning. [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php Add onclick events on intersections in .js, calling an action with appropriate parameters Add action in .action.php, retrieving parameters and calling the appropriate game action. Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’ Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. The basic game turn is implemented: you can drop some stones! [[File:Gomoku tuto4.png]] == Cleanup == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game condition(s) == Implement specific rules for the game (if any) Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js Test everything thoroughly... you are done! [[File:Gomoku tuto6.png]] 770a1936ddb073d24fc46111d83b4de2f07be7e9 356 355 2012-12-05T21:14:15Z Een 3 /* Start from the emtpy game template */ wikitext text/x-wiki == Start from the emtpy game template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Edit .tpl & .css to add the board : [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit .sql to create a table for intersections. Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database. Edit .game.php->getAllDatas to retrieve the state of the intersections from the database. Edit .tpl to create a template for intersections (jstpl_intersection). Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning. [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php Add onclick events on intersections in .js, calling an action with appropriate parameters Add action in .action.php, retrieving parameters and calling the appropriate game action. Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’ Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. The basic game turn is implemented: you can drop some stones! [[File:Gomoku tuto4.png]] == Cleanup == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game condition(s) == Implement specific rules for the game (if any) Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js Test everything thoroughly... you are done! [[File:Gomoku tuto6.png]] e4b849c06439e1657646ff876b0611ecc4b37c58 357 356 2012-12-05T21:17:54Z Een 3 wikitext text/x-wiki == Start from the emtpy game template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Edit .tpl to add some div for the board in the HTML. Edit .css to show the image of the board as background. [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit .sql to create a table for intersections. Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database. Edit .game.php->getAllDatas to retrieve the state of the intersections from the database. Edit .tpl to create a template for intersections (jstpl_intersection). Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning. [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php Add onclick events on intersections in .js, calling an action with appropriate parameters Add action in .action.php, retrieving parameters and calling the appropriate game action Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’ Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. The basic game turn is implemented: you can drop some stones! [[File:Gomoku tuto4.png]] == Cleanup == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game condition(s) == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 5459b575222bb6886bbc92e33b2526c342c0f163 358 357 2012-12-05T21:18:27Z Een 3 /* Setup the board */ wikitext text/x-wiki == Start from the emtpy game template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some div for the board in the HTML. Edit .css to show the image of the board as background. [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit .sql to create a table for intersections. Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database. Edit .game.php->getAllDatas to retrieve the state of the intersections from the database. Edit .tpl to create a template for intersections (jstpl_intersection). Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning. [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php Add onclick events on intersections in .js, calling an action with appropriate parameters Add action in .action.php, retrieving parameters and calling the appropriate game action Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’ Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. The basic game turn is implemented: you can drop some stones! [[File:Gomoku tuto4.png]] == Cleanup == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game condition(s) == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 333f80b42a2a4503200c1d2594d04917358be984 359 358 2012-12-05T21:24:48Z Een 3 wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == Start from the emtpy game template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some div for the board in the HTML. Edit .css to show the image of the board as background. [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit .sql to create a table for intersections. Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database. Edit .game.php->getAllDatas to retrieve the state of the intersections from the database. Edit .tpl to create a template for intersections (jstpl_intersection). Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning. [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php Add onclick events on intersections in .js, calling an action with appropriate parameters Add action in .action.php, retrieving parameters and calling the appropriate game action Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’ Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. The basic game turn is implemented: you can drop some stones! [[File:Gomoku tuto4.png]] == Cleanup == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game condition(s) == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 9eb647a35af1b562d14557cf16d235693d35e22b 360 359 2012-12-05T21:25:33Z Een 3 /* Start from the emtpy game template */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some div for the board in the HTML. Edit .css to show the image of the board as background. [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit .sql to create a table for intersections. Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database. Edit .game.php->getAllDatas to retrieve the state of the intersections from the database. Edit .tpl to create a template for intersections (jstpl_intersection). Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning. [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php Add onclick events on intersections in .js, calling an action with appropriate parameters Add action in .action.php, retrieving parameters and calling the appropriate game action Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’ Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. The basic game turn is implemented: you can drop some stones! [[File:Gomoku tuto4.png]] == Cleanup == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game condition(s) == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 5a68b325ce531060787304be7f314dfe7510e33e 361 360 2012-12-05T21:26:10Z Een 3 /* Cleanup */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some div for the board in the HTML. Edit .css to show the image of the board as background. [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit .sql to create a table for intersections. Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database. Edit .game.php->getAllDatas to retrieve the state of the intersections from the database. Edit .tpl to create a template for intersections (jstpl_intersection). Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning. [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php Add onclick events on intersections in .js, calling an action with appropriate parameters Add action in .action.php, retrieving parameters and calling the appropriate game action Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’ Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. The basic game turn is implemented: you can drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game condition(s) == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 994f40b68cfbaccf00b4bea0f7b2483b6370095e 362 361 2012-12-05T21:26:20Z Een 3 /* Implement rules and end of game condition(s) */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some div for the board in the HTML. Edit .css to show the image of the board as background. [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit .sql to create a table for intersections. Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database. Edit .game.php->getAllDatas to retrieve the state of the intersections from the database. Edit .tpl to create a template for intersections (jstpl_intersection). Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning. [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php Add onclick events on intersections in .js, calling an action with appropriate parameters Add action in .action.php, retrieving parameters and calling the appropriate game action Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’ Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. The basic game turn is implemented: you can drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 812c4fea187e9a853f3dcbd0588770c7c11c1065 364 362 2012-12-05T21:58:44Z Een 3 /* Setup the board */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit .sql to create a table for intersections. Edit .game.php->setupNewGame to insert the empty intersections (19x19) with coordinates into the database. Edit .game.php->getAllDatas to retrieve the state of the intersections from the database. Edit .tpl to create a template for intersections (jstpl_intersection). Edit .js to setup the intersections layer that will be used to get click events and to display the stones. Use some temporary css colors on borders or background+opacity to make sure they are positioned right. You can declare some constants in material.inc.php and pass them to your .js through .game.php->getAllDatas for easy repositioning. [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php Add onclick events on intersections in .js, calling an action with appropriate parameters Add action in .action.php, retrieving parameters and calling the appropriate game action Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’ Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. The basic game turn is implemented: you can drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] c0758d7154977a6725932786631d490d8a63eaba 365 364 2012-12-05T22:13:33Z Een 3 /* Setup the backbone of your game */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit .sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> And pass them to your gomoku.js through gomoku.game.php->getAllDatas() for easy repositioning (modify constant, refresh). // Constants $result['constants'] = $this->gameConstants; Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php Add onclick events on intersections in .js, calling an action with appropriate parameters Add action in .action.php, retrieving parameters and calling the appropriate game action Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’ Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. The basic game turn is implemented: you can drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 26ac9382325c962f7620ffdf4174e385a7ee1023 366 365 2012-12-05T22:13:56Z Een 3 /* Setup the backbone of your game */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> And pass them to your gomoku.js through gomoku.game.php->getAllDatas() for easy repositioning (modify constant, refresh). // Constants $result['constants'] = $this->gameConstants; Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php Add onclick events on intersections in .js, calling an action with appropriate parameters Add action in .action.php, retrieving parameters and calling the appropriate game action Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’ Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. The basic game turn is implemented: you can drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 842acc557f3052d95e38808148093d8e057a3a76 367 366 2012-12-05T22:18:34Z Een 3 /* Setup the backbone of your game */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> And pass them to your gomoku.js for easy repositioning (modify constant, refresh). * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php Add onclick events on intersections in .js, calling an action with appropriate parameters Add action in .action.php, retrieving parameters and calling the appropriate game action Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’ Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. The basic game turn is implemented: you can drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] a4b0f28f38a333e965030c81d36ed6b23dea298f 368 367 2012-12-05T22:20:55Z Een 3 /* Setup the backbone of your game */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constant values have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php Add onclick events on intersections in .js, calling an action with appropriate parameters Add action in .action.php, retrieving parameters and calling the appropriate game action Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’ Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. The basic game turn is implemented: you can drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 89de825d4f23bd359ed656f28be811507ee532a8 369 368 2012-12-05T22:21:30Z Een 3 /* Setup the backbone of your game */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php Add onclick events on intersections in .js, calling an action with appropriate parameters Add action in .action.php, retrieving parameters and calling the appropriate game action Add game action in .game.php to update the database, then notify the client using a method ‘stonePlayed’ Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. The basic game turn is implemented: you can drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 05743b8feac3d4829fc79918f260e21ad40b936d 370 369 2012-12-05T22:36:37Z Een 3 /* Manage states and events */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Add onclick events on intersections in gomoku.js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } Implement this method in javascript to update the intersection to show the stone, and register it inside the setNotifications function. notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, For this function, you need to declare a stone javascript template in your .tpl file var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 2b3fc4e1c8667563a2f5381b7c87a523442c89d4 371 370 2012-12-05T22:40:51Z Een 3 /* Manage states and events */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Add onclick events on intersections in gomoku.js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; * to define the css styles for the stones .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } These styles rely on an image of both the white and black stones, and position the background appropriately to show only the part of the background image matching the appropriate stone. The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] b4fe94be1cfe6d346bb1587062e3544b3bd7e297 373 371 2012-12-05T22:45:13Z Een 3 /* Manage states and events */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Add onclick events on intersections in gomoku.js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an image of both the white and black stones, and position the background appropriately to show only the part of the background image matching the appropriate stone or the white space if there is no stone. Here is what the image looks like (we will use the red circle later on): [[File:Gomoku stones.png]] The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 704504582a9dcb58e10995b39556b6e30a037514 374 373 2012-12-05T22:48:00Z Een 3 /* Manage states and events */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Add onclick events on intersections in gomoku.js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like (we will use the red circle later on): [[File:Gomoku stones.png]] The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] d5c4971530420428f040193ef825f9854005ff6e 375 374 2012-12-05T22:55:18Z Een 3 /* Manage states and events */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Add onclick events on intersections in gomoku.js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game (if any) Nothing special for Gomoku Implement rule for computing game progression in .game.php->getGameProgression() Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 779b1978f9b35636690f0a59f27ce681c331b559 377 375 2012-12-05T23:06:25Z Een 3 /* Implement rules and end of game conditions */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Add onclick events on intersections in gomoku.js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner in .game.php->stCheckEndOfGame() Notify the score and implement the corresponding interface update in .js '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 43b1670c24100dd1aa9409735a8497555c99d047 393 377 2012-12-06T22:07:37Z Een 3 /* Implement rules and end of game conditions */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Add onclick events on intersections in gomoku.js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner in gomoku.game.php->stCheckEndOfGame() * It is easier to check for a win directly after setting the stone, so: ** we declare a global 'end_of_game' variable in gomoku.game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); ** we init that global variable to 0 in gomoku.game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); ** we add the appropriate code in gomoku.game.php before proceeding to the next state, using a checkForWin() function that we implement separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() which is called when your state machine goes to the 'checkEndOfGame' state, you check for this variable and for other 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * We catch the score notification on the client side in gomoku.js->setupNotifications() and we set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * We implement the function declared to handle the notification. notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] b15b86e48944c4f923af7ef297aa6a697eeeb1d3 394 393 2012-12-06T22:09:13Z Een 3 /* Implement rules and end of game conditions */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Add onclick events on intersections in gomoku.js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * we declare a global 'end_of_game' variable in gomoku.game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * we init that global variable to 0 in gomoku.game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * we add the appropriate code in gomoku.game.php before proceeding to the next state, using a checkForWin() function that we implement separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() which is called when your state machine goes to the 'checkEndOfGame' state, you check for this variable and for other 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * We catch the score notification on the client side in gomoku.js->setupNotifications() and we set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * We implement the function declared to handle the notification. notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 44aa0b4f13643a40db740d0e30d5fba5828e6493 395 394 2012-12-06T22:10:32Z Een 3 /* Implement rules and end of game conditions */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Add onclick events on intersections in gomoku.js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * we declare a global 'end_of_game' variable in gomoku.game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * we init that global variable to 0 in gomoku.game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * we add the appropriate code in gomoku.game.php before proceeding to the next state, using a checkForWin() function that we implement separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, you check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * We catch the score notification on the client side in gomoku.js->setupNotifications() and we set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * We implement the function declared to handle the notification. notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 52031b9a65d85144687c385bb98224a18b1c90ae 396 395 2012-12-06T22:12:25Z Een 3 /* Implement rules and end of game conditions */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Add onclick events on intersections in gomoku.js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in gomoku.game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * we init that global variable to 0 in gomoku.game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in gomoku.game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in gomoku.js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 77087421e739e44ab260cdb86601e5a2c38b6915 397 396 2012-12-06T22:15:10Z Een 3 /* Manage states and events */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in gomoku.game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in gomoku.js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in gomoku.game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * we init that global variable to 0 in gomoku.game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in gomoku.game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in gomoku.js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] e369ecff0c1d3a7db33d7af073473f038c059ff9 398 397 2012-12-06T22:16:01Z Een 3 /* Setup the board */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections (jstpl_intersection). <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in gomoku.game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in gomoku.js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in gomoku.game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * we init that global variable to 0 in gomoku.game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in gomoku.game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in gomoku.js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 2a35d8692c6958f159f309735364afa225f17b63 Studio FAQ 0 53 363 347 2012-12-05T21:45:22Z Een 3 wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. cb1693b12ae4ed239fcfaa093165d65ff0849426 390 363 2012-12-06T21:43:08Z Een 3 wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. 49c74b0ae1da806be0026784581066e1b1ae1b64 Restr:Gomoku stones.png 6 80 372 2012-12-05T22:45:06Z Een 3 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Tutorial reversi 0 57 376 323 2012-12-05T23:05:05Z Pikiou 1872 Typos wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_disc" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it. At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state: <pre> function stNextPlayer() { // Active next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appears automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handle the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Made these discs blinking and set them to the specified color for( var i in notif.args.turnedOver ) { var disc = notif.args.turnedOver[ i ]; // Make the disc blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'disccolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 5735d4c608381a182395d0aeed7517711422fc58 378 376 2012-12-05T23:10:00Z Pikiou 1872 Buggy code result of mixing the words disc and token wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${xy}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { xy: x+''+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+''+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+''+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it. At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state: <pre> function stNextPlayer() { // Active next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appears automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handle the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Made these discs blinking and set them to the specified color for( var i in notif.args.turnedOver ) { var disc = notif.args.turnedOver[ i ]; // Make the disc blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'disccolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". c86f6bd8839862875261fc3c1f99193e43decdc8 379 378 2012-12-05T23:11:55Z Pikiou 1872 Buggy code because of a missing underscore between x and y wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one database entry for each square, with a "NULL" value which mean "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we active the first player to make it active at the beginning of the game. Now, we need to make these tokens appears on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that format the result of this SQL query in a PHP array with x, y and player attribute. The last thing we need to do is to process this array on client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it. At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state: <pre> function stNextPlayer() { // Active next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appears automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handle the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Made these discs blinking and set them to the specified color for( var i in notif.args.turnedOver ) { var disc = notif.args.turnedOver[ i ]; // Make the disc blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'disccolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". e10e837e5c2636c2340994157b3085c572f3e307 380 379 2012-12-06T00:36:07Z Pikiou 1872 /* Setup the initial game position */ Typos wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it. At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state: <pre> function stNextPlayer() { // Active next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appears automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handle the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Made these discs blinking and set them to the specified color for( var i in notif.args.turnedOver ) { var disc = notif.args.turnedOver[ i ]; // Make the disc blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'disccolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 5c64283860e84e2f59acc0cd203849a21a95e15b 381 380 2012-12-06T01:12:25Z Pikiou 1872 /* Setup the initial game position */ $blackplayer_id and $whiteplayer_id weren't defined wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it. At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state: <pre> function stNextPlayer() { // Active next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appears automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handle the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Made these discs blinking and set them to the specified color for( var i in notif.args.turnedOver ) { var disc = notif.args.turnedOver[ i ]; // Make the disc blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'disccolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 97a7cd5873575fc05bf2f8f58afb59ef3699ee58 382 381 2012-12-06T01:20:35Z Pikiou 1872 /* The discs */ Set player colors to white and black wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi game, it's very simple although. Here's a diagram of our game state machine for Reversi: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in our reversi.game.php file the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it. At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state: <pre> function stNextPlayer() { // Active next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appears automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handle the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Made these discs blinking and set them to the specified color for( var i in notif.args.turnedOver ) { var disc = notif.args.turnedOver[ i ]; // Make the disc blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'disccolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 1506c28901430d0ff115464f36c7b1e6868aa63f 383 382 2012-12-06T02:07:54Z Pikiou 1872 /* The game state machine */ Typos wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it. At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state: <pre> function stNextPlayer() { // Active next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appears automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handle the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Made these discs blinking and set them to the specified color for( var i in notif.args.turnedOver ) { var disc = notif.args.turnedOver[ i ]; // Make the disc blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'disccolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 798fcf2511667129243ba3665423ad2815dbad92 384 383 2012-12-06T12:08:18Z Pikiou 1872 /* Display allowed moves */ Missing the possibleMove class CSS declaration wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves that our PHP "updatePossibleMoves" create for us, and add the "possibleMove" class to corresponding square. Finally, we use BGA framework "addTooltipToClass" method to associate a tooltip to all these highlighted squares in order players can understand the meaning of this. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state: <pre> function stNextPlayer() { // Active next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appears automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handle the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Made these discs blinking and set them to the specified color for( var i in notif.args.turnedOver ) { var disc = notif.args.turnedOver[ i ]; // Make the disc blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'disccolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 39ed1b8df7b3fc58dc4c7a6c1fe1286413cab9bc 385 384 2012-12-06T12:11:08Z Pikiou 1872 /* Display allowed moves */ Typos wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 56px; height: 56px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state: <pre> function stNextPlayer() { // Active next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appears automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handle the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Made these discs blinking and set them to the specified color for( var i in notif.args.turnedOver ) { var disc = notif.args.turnedOver[ i ]; // Make the disc blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'disccolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". fe70922d87a5d2f33217e98ae8fb82131665a115 386 385 2012-12-06T12:28:33Z Pikiou 1872 /* Make the squares appears */ Squares didn't fill their space wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * On server side, check the move is correct, apply Reversi rules and jump to next player. * On client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone click on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). A last thing to do on the server side is to active the next player when we enter in the "nextPlayer" game state: <pre> function stNextPlayer() { // Active next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appears automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handle the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Made these discs blinking and set them to the specified color for( var i in notif.args.turnedOver ) { var disc = notif.args.turnedOver[ i ]; // Make the disc blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'disccolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 37dba66a4ed6f61ec2a854bcc3923bbe996220a7 387 386 2012-12-06T15:30:58Z Pikiou 1872 /* Let's play */ Typos wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appears automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handle the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Made these discs blinking and set them to the specified color for( var i in notif.args.turnedOver ) { var disc = notif.args.turnedOver[ i ]; // Make the disc blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'disccolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 156ea2f58083036772ef8343548e257ae8345b4a 388 387 2012-12-06T15:32:18Z Pikiou 1872 /* Let's play */ Need to initialize statistics wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in state.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appears automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handle the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Made these discs blinking and set them to the specified color for( var i in notif.args.turnedOver ) { var disc = notif.args.turnedOver[ i ]; // Make the disc blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ), dojo.fadeOut( { node: 'disc_'+disc.x+''+disc.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'disccolor_000000', 'disccolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'disccolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'disc_'+disc.x+''+disc.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of it. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 0618aa74ff1170f381a45a8f753790836619cea2 389 388 2012-12-06T16:33:49Z Pikiou 1872 /* Make the move appears automatically */ Typos wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "stats.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in state.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 9bf25b0bffa92efc21acecec6a36e5d946859991 Studio back-office 0 56 391 313 2012-12-06T21:43:49Z Een 3 /* Sources */ wikitext text/x-wiki You will find the URL to the Studio back-office in the 'resources.html' file at the root of your SFTP access. Here is a list and description of the links and functions in this back-office. Click on a menu to display its content. === Documentation === Contains links to this wiki, the development forum and the bugs forum. === Database === Contains a link to the Studio database administration tool (PHPMyAdmin). Your login / password for this tool is the same as for your SFTP access. === Sources === Contains a form for committing your sources to the BGA repository. * Game name field should contain the name of your game (lower case, no space). Ex: puertorico * Comment field should contain your commit comment describing changes to the code since your last commit. You should commit from time to time when you hit some landmarks in your development. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. === Logs === Gives you a web based access to the studio server logs. ; Current table error log : main log of interest to you while developing, it contains the error happening at the table you are currently playing at. ; Current table request logs : this log traces all the actions happening at the table you are currently playing at. ; Javascript error log : this log traces all the Javascript errors happening on the client side. Errors are also briefly displayed in your browser, but in this log it's better formatted and you can look a it quietly. ; Gameserver error log : this log traces all errors happening on the gameserver. It should mainly be useful if your game setup crashes (ie before your table is ready, so before errors are collected in the current table error log), for example if there is a syntax error in your 'dbmodel.sql' file. ; HTTP error log : this log traces the web server errors. This is useful to look at PHP syntax errors and warnings. Please note that the three last logs are common to all games being developed on the platform, so there may be some noise in the data you are interested in. You can open the log links in a different tab and just hit F5 when you need to refresh. The URL you will get for the new tab has a "?n=100" parameter that gives the number of lines to display: you can modify it in the URL if you need more. b8fd0f6cc336100886af11fe1c0b50fea185e534 Studio function reference 0 55 392 327 2012-12-06T22:06:45Z Een 3 /* Client side (Javascript functions) */ wikitext text/x-wiki This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to). This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below. == Server side (PHP functions) == === APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false ) : Get script argument with the correct type : bCanFail means than a validation failure is possible (user input) : The main argType values are as follows. <pre> define( 'AT_int', 0 ); // an integer define( 'AT_posint', 1 ); // a positive integer define( 'AT_float', 2 ); // a float define( 'AT_email', 3 ); // an email define( 'AT_url', 4 ); // a URL define( 'AT_bool', 5 ); // 1/0/true/false define( 'AT_enum', 6 ); // argTypeDetails list the possible values define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space </pre> === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value ; function DbQuery( $sql ) : Executes sql query on the database ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty. ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found : Raise an exception if more than 1 row is returned ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. == Client side (Javascript functions) == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 6d38dcd8680be3c28de97befb1efdaa8f385d027 Tutorial gomoku 0 73 399 398 2012-12-06T22:17:16Z Een 3 /* Setup the backbone of your game */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit gomoku.game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit gomoku.game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit gomoku.js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in gomoku.game.php->getAllDatas() is now available in your gomoku.js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your gomoku.js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your gomoku.game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In gomoku.game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In gomoku.js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in gomoku.game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in gomoku.js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding gomoku.js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in gomoku.action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in gomoku.game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in gomoku.js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in gomoku.js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in gomoku.game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in gomoku.game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in gomoku.game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * we init that global variable to 0 in gomoku.game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in gomoku.game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in gomoku.js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] bfb8e63de4f2e6318889b6e22a427809c8949c3c 400 399 2012-12-06T22:19:30Z Een 3 wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created : [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * we init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 54ee41a684ba1db25a6c94e6715491f67ca872f8 401 400 2012-12-06T22:19:41Z Een 3 /* You will start from our 'emtpy game' template */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created: [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * we init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 751fd879e8fc20a5a4276b292a84a8fc69aeed72 402 401 2012-12-06T22:21:47Z Een 3 /* Setup the backbone of your game */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created: [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * In .js->setup() assign the constants to this variable this.gameConstants = gamedatas.constants; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * we init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 87d10ec1ed913f5e43d8a32370d7bda0e373fadf 403 402 2012-12-06T22:22:43Z Een 3 /* Setup the backbone of your game */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created: [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * In .js->setup() assign the constants to this variable this.gameConstants = gamedatas.constants; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get after some tweaks and refresh: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * we init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 4e63521137d4911761e2ace1450021690f87d429 404 403 2012-12-06T22:23:06Z Een 3 /* Setup the backbone of your game */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created: [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * In .js->setup() assign the constants to this variable this.gameConstants = gamedatas.constants; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states. One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * we init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 87d10ec1ed913f5e43d8a32370d7bda0e373fadf 405 404 2012-12-06T22:24:28Z Een 3 /* Manage states and events */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created: [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * In .js->setup() assign the constants to this variable this.gameConstants = gamedatas.constants; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * we init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] d1f9ba2385a1a391c47d8959c71dba650410cd96 406 405 2012-12-06T22:26:48Z Een 3 /* Implement rules and end of game conditions */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created: [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * In .js->setup() assign the constants to this variable this.gameConstants = gamedatas.constants; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, notify it to update the score on the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] aacabbe7efb7c6b91947fe7a33b4e170d580f067 407 406 2012-12-06T22:27:38Z Een 3 /* Implement rules and end of game conditions */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created: [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * In .js->setup() assign the constants to this variable this.gameConstants = gamedatas.constants; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1000 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 'auto' ); })); slide.play(); // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, send a score update notification to the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 5ffdfba9f0e591c1b7eee1236e59ba7b7ffc2c94 Studio 0 49 408 343 2012-12-06T22:29:11Z Een 3 /* Great, I'm in! ... How should I start? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum) <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 2f629611da109a5f3e8c61e0d395592c19b646ef 409 408 2012-12-07T10:09:19Z Sourisdudesert 1 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum) <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 4776ee490903437bd94367e54ca55ff5d0e80636 414 409 2012-12-11T14:48:31Z Een 3 /* How do I register? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is this? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your player user name on BGA * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum) <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] f2d26be5ae879cac19e56ee406d83528b3d57077 428 414 2013-01-05T09:35:34Z Sourisdudesert 1 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == How can I develop a board game on BGA Studio? == Check these presentations first: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your player user name on BGA * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum) <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] a91516e964e65f1efa5a28e4ab7e4121bf38ea02 429 428 2013-01-05T09:41:36Z Sourisdudesert 1 /* How can I develop a board game on BGA Studio? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How do I register? == Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your player user name on BGA * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum) <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] dc62fcaa145e23c1d275111856dc5c7d56a8afb7 430 429 2013-01-05T09:46:29Z Sourisdudesert 1 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] aa67d4007c5a725783c814eefd8d15c3745f1878 432 430 2013-01-05T09:47:50Z Sourisdudesert 1 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == Other resources == [[Studio FAQ]] [[Studio file reference]] [[Studio function reference]] [[Studio back-office]] [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] e2f3e477cb0aa6465e28ac5c6fbd0159b5cddd76 433 432 2013-01-05T09:55:12Z Sourisdudesert 1 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference]] [[Studio function reference]] === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] a08a63f342a76db9ad2d456591e2f4759344c61f 434 433 2013-01-05T09:58:34Z Sourisdudesert 1 /* BGA Studio Framework reference */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|Files structure of a BGA game]] [[Studio function reference]] === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] e6490a1a2089cdb7871765132f3f8d702ac1853c 435 434 2013-01-05T09:59:06Z Sourisdudesert 1 /* BGA Studio Framework reference */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] [[Studio function reference]] === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] d3b8d6a65251dce3e3e8ceb78bfa73c42efb0f65 436 435 2013-01-05T10:08:56Z Sourisdudesert 1 /* BGA Studio Framework reference */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== [[Main game logic (<gamename>.game.php)]] [[Your game state machine (states.inc.php)]] [[Game database model (dbmodel.sql)]] [[Players actions (<gamename>.action.php)]] [[Game material description (material.inc.php)]] [[Game statistics (stats.inc.php)]] ==== Game interface ==== [[Game interface logic (<gamename>.js)]] [[Game art (img directory)]] [[Game interface stylesheet (<gamename>.css)]] [[Game layout: view and template (<gamename>.view.php and <gamename>_<gamename>.tpl)]] ==== Other components === [[Game options and preferences (gameoptions.inc.php)]] [[Studio function reference]] === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] f40cffdcec66a058431e166fc222e144c5b19136 437 436 2013-01-05T10:09:07Z Sourisdudesert 1 /* BGA Studio documentation */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== [[Main game logic (<gamename>.game.php)]] [[Your game state machine (states.inc.php)]] [[Game database model (dbmodel.sql)]] [[Players actions (<gamename>.action.php)]] [[Game material description (material.inc.php)]] [[Game statistics (stats.inc.php)]] ==== Game interface ==== [[Game interface logic (<gamename>.js)]] [[Game art (img directory)]] [[Game interface stylesheet (<gamename>.css)]] [[Game layout: view and template (<gamename>.view.php and <gamename>_<gamename>.tpl)]] ==== Other components ==== [[Game options and preferences (gameoptions.inc.php)]] [[Studio function reference]] === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] aefa09e482bda70b699e7e2e8febb638d76e4ebc 438 437 2013-01-05T10:10:34Z Sourisdudesert 1 /* BGA Studio documentation */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic (yourgamename.game.php)]] * [[Your game state machine (states.inc.php)]] * [[Game database model (dbmodel.sql)]] * [[Players actions (yourgamename.action.php)]] * [[Game material description (material.inc.php)]] * [[Game statistics (stats.inc.php)]] ==== Game interface ==== * [[Game interface logic (yourgamename.js)]] * [[Game art (img directory)]] * [[Game interface stylesheet (yourgamename.css)]] * [[Game layout: view and template (yourgamename.view.php and yourgamename_yourgamename.tpl)]] ==== Other components ==== * [[Game options and preferences (gameoptions.inc.php)]] [[Studio function reference]] === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 1072c45c47be8bd6020ce2a38ed8a472b8cc97cf 441 438 2013-01-05T10:14:00Z Sourisdudesert 1 /* BGA Studio documentation */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic (yourgamename.js)]] * [[Game art (img directory)]] * [[Game interface stylesheet (yourgamename.css)]] * [[Game layout: view and template (yourgamename.view.php and yourgamename_yourgamename.tpl)]] ==== Other components ==== * [[Game options and preferences (gameoptions.inc.php)]] [[Studio function reference]] === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] fd2c9b3cfb81e63f498e7363e2a6550c66091a2f Studio FAQ 0 53 410 390 2012-12-09T20:19:37Z Een 3 wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the Developer tools with Chrome which has about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the save/restore functionality (NB: currently non functional, will be ok with the next studio update). It enable you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. ef1e7e780ff9d182e7f6232aae6cca4f1616f718 411 410 2012-12-09T20:21:23Z Een 3 /* What is the best way to debug? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the Developer tools with Chrome which has about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality (NB: currently non functional, will be ok with the next studio update). It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. f65463a81a57517a503e0f7b4adc233b9926ba58 412 411 2012-12-09T20:42:02Z Een 3 /* What is the best way to debug? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the Developer tools with Chrome which has about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. a244da1f57822595825408622baa1c79d71d759f 413 412 2012-12-09T20:46:36Z Een 3 /* What is the best way to debug? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. 4a1d7d389aee2ef5066258585ecfc2056b52cde0 420 413 2012-12-23T17:17:40Z Een 3 /* What is the best way to debug? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389: Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. dd8456a862c8ae6069b019e08227068406386654 421 420 2012-12-23T17:18:00Z Een 3 /* Some frequent errors */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. 03c40861e6f13964b3afa0ce1e9f0d483e12882a The Boss 0 46 415 217 2012-12-15T07:48:27Z Sweetnaty 1920 /* Description */ wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! '''Цель игры.''' 1. В конце раунда игрок с наибольшим количеством гангстеров в городе выигрывают карту города, расположенную рубашкой вверх (лицом в низ. 2. В конце игры выигрывают игроки которые больше всего заработали миллионов. ''' Описание''' В каждом городе, кроме Чикаго, имеется карта расположенная рубашкой вверх. Остальная часть карт распределена между игроками. Каждый игрок может видеть цвета карт других участников. '''Раунд:''' 1. Расположить гангстеров в городе (большие кубики – «гангстеры – эксперты») они возвращаются обратно к игроку в конце раунда (если не были убиты, заключены под стражу или не попали в больницу). Маленькие кубики – «гангстеры- новички», в конце раунда не возвращаются. Чтобы выиграть карту города, ваших гангстеров в городе должно быть больше, чем у противников. 2. После расположения гангстеров в городе, вы должны обязательно выложить одну карту с вашей руки. На этом ваш ход заканчиватеся. Когда у каждого игрока остается по две карты на руках, открывается карта полиции. Игра заканчивается, если открыты карты полиции с тремя одинаковыми по цвету значками. ''Если вы выигрываете « пистолет», то ваш гангстер убит, если «решетка» – гангстер не участвует в игре в течение 2-ух раундов, если "больница"(красный крест) - гангстер не участвует в игре в течение 1 раунда. Если Вы получаете вычеркнутую карту человека в Цинциннати, вам запрещено располагать гангстеров в этом городе до конца игры.'' '''Карта Чикаго(Алькапоне).''' У Чикаго (Алькапоне) нет скрытой карты, вместо этого игрок, сыгравший гангстеров в Чикаго, делит выигрышные деньги из городов расположенных слева от него (Чикаго) и делит их с Алькапоне, с округлением в меньшую сторону. '''Подсказки новичкам.''' Гангстеров не обязательно выкладывать каждый раунд, обязательным является выложить карту города с вашей руки. Можно дождаться пока ваши противники начнут выкладывать карты с руки, чтобы понять, где можно заработать миллион. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. *If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. ec426d7a7f218f82ecde489ba149533dc36b1aa3 416 415 2012-12-15T07:48:54Z Sweetnaty 1920 /* Goal */ wikitext text/x-wiki '''Цель игры.''' 1. В конце раунда игрок с наибольшим количеством гангстеров в городе выигрывают карту города, расположенную рубашкой вверх (лицом в низ. 2. В конце игры выигрывают игроки которые больше всего заработали миллионов. ''' Описание''' В каждом городе, кроме Чикаго, имеется карта расположенная рубашкой вверх. Остальная часть карт распределена между игроками. Каждый игрок может видеть цвета карт других участников. '''Раунд:''' 1. Расположить гангстеров в городе (большие кубики – «гангстеры – эксперты») они возвращаются обратно к игроку в конце раунда (если не были убиты, заключены под стражу или не попали в больницу). Маленькие кубики – «гангстеры- новички», в конце раунда не возвращаются. Чтобы выиграть карту города, ваших гангстеров в городе должно быть больше, чем у противников. 2. После расположения гангстеров в городе, вы должны обязательно выложить одну карту с вашей руки. На этом ваш ход заканчиватеся. Когда у каждого игрока остается по две карты на руках, открывается карта полиции. Игра заканчивается, если открыты карты полиции с тремя одинаковыми по цвету значками. ''Если вы выигрываете « пистолет», то ваш гангстер убит, если «решетка» – гангстер не участвует в игре в течение 2-ух раундов, если "больница"(красный крест) - гангстер не участвует в игре в течение 1 раунда. Если Вы получаете вычеркнутую карту человека в Цинциннати, вам запрещено располагать гангстеров в этом городе до конца игры.'' '''Карта Чикаго(Алькапоне).''' У Чикаго (Алькапоне) нет скрытой карты, вместо этого игрок, сыгравший гангстеров в Чикаго, делит выигрышные деньги из городов расположенных слева от него (Чикаго) и делит их с Алькапоне, с округлением в меньшую сторону. '''Подсказки новичкам.''' Гангстеров не обязательно выкладывать каждый раунд, обязательным является выложить карту города с вашей руки. Можно дождаться пока ваши противники начнут выкладывать карты с руки, чтобы понять, где можно заработать миллион. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. *If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. 881a4b4353af0bd885bae8ed8e22b845fd106ad1 417 416 2012-12-15T07:49:42Z Sweetnaty 1920 /* Beginner Tips */ wikitext text/x-wiki '''Цель игры.''' 1. В конце раунда игрок с наибольшим количеством гангстеров в городе выигрывают карту города, расположенную рубашкой вверх (лицом в низ. 2. В конце игры выигрывают игроки которые больше всего заработали миллионов. ''' Описание''' В каждом городе, кроме Чикаго, имеется карта расположенная рубашкой вверх. Остальная часть карт распределена между игроками. Каждый игрок может видеть цвета карт других участников. '''Раунд:''' 1. Расположить гангстеров в городе (большие кубики – «гангстеры – эксперты») они возвращаются обратно к игроку в конце раунда (если не были убиты, заключены под стражу или не попали в больницу). Маленькие кубики – «гангстеры- новички», в конце раунда не возвращаются. Чтобы выиграть карту города, ваших гангстеров в городе должно быть больше, чем у противников. 2. После расположения гангстеров в городе, вы должны обязательно выложить одну карту с вашей руки. На этом ваш ход заканчиватеся. Когда у каждого игрока остается по две карты на руках, открывается карта полиции. Игра заканчивается, если открыты карты полиции с тремя одинаковыми по цвету значками. ''Если вы выигрываете « пистолет», то ваш гангстер убит, если «решетка» – гангстер не участвует в игре в течение 2-ух раундов, если "больница"(красный крест) - гангстер не участвует в игре в течение 1 раунда. Если Вы получаете вычеркнутую карту человека в Цинциннати, вам запрещено располагать гангстеров в этом городе до конца игры.'' '''Карта Чикаго(Алькапоне).''' У Чикаго (Алькапоне) нет скрытой карты, вместо этого игрок, сыгравший гангстеров в Чикаго, делит выигрышные деньги из городов расположенных слева от него (Чикаго) и делит их с Алькапоне, с округлением в меньшую сторону. '''Подсказки новичкам.''' Гангстеров не обязательно выкладывать каждый раунд, обязательным является выложить карту города с вашей руки. Можно дождаться пока ваши противники начнут выкладывать карты с руки, чтобы понять, где можно заработать миллион. b47bbe214e6ce4ab1cc0aa683a747d92216769da 418 417 2012-12-15T18:40:21Z Sweetnaty 1920 wikitext text/x-wiki '''Цель игры.''' 1. В конце раунда игрок с наибольшим количеством гангстеров в городе выигрывают карту города, расположенную рубашкой вверх (лицом вниз). 2. В конце игры выигрывают игроки которые больше всего заработали миллионов. ''' Описание''' В каждом городе, кроме Чикаго, имеется карта расположенная рубашкой вверх. Остальная часть карт распределена между игроками. Каждый игрок может видеть цвета карт других участников. '''Раунд:''' 1. Расположить гангстеров в городе (большие кубики – «гангстеры – эксперты») они возвращаются обратно к игроку в конце раунда (если не были убиты, заключены под стражу или не попали в больницу). Маленькие кубики – «гангстеры- новички», в конце раунда не возвращаются. Чтобы выиграть карту города, ваших гангстеров в городе должно быть больше, чем у противников. 2. После расположения гангстеров в городе, вы должны обязательно выложить одну карту с вашей руки. На этом ваш ход заканчиватеся. Когда у каждого игрока остается по две карты на руках, открывается карта полиции. Игра заканчивается, если открыты карты полиции с тремя одинаковыми по цвету значками. ''Если вы выигрываете « пистолет», то ваш гангстер убит, если «решетка» – гангстер не участвует в игре в течение 2-ух раундов, если "больница"(красный крест) - гангстер не участвует в игре в течение 1 раунда. Если Вы получаете вычеркнутую карту человека в Цинциннати, вам запрещено располагать гангстеров в этом городе до конца игры.'' '''Карта Чикаго(Алькапоне).''' У Чикаго (Алькапоне) нет скрытой карты, вместо этого игрок, сыгравший гангстеров в Чикаго, делит выигрышные деньги из городов расположенных слева от него (Чикаго) и делит их с Алькапоне, с округлением в меньшую сторону. '''Подсказки новичкам.''' Гангстеров не обязательно выкладывать каждый раунд, обязательным является выложить карту города с вашей руки. Можно дождаться пока ваши противники начнут выкладывать карты с руки, чтобы понять, где можно заработать миллион. 45d5f6a85beada1c1bf36cf6ec5b930d4354e8f2 419 418 2012-12-15T18:41:21Z Sweetnaty 1920 wikitext text/x-wiki '''Цель игры.''' 1. В конце раунда игрок с наибольшим количеством гангстеров в городе выигрывают карту города, расположенную рубашкой вверх (лицом вниз). 2. В конце игры выигрывают игроки которые больше всего заработали миллионов. ''' Описание'''''' ''' В каждом городе, кроме Чикаго, имеется карта расположенная рубашкой вверх. Остальная часть карт распределена между игроками. Каждый игрок может видеть цвета карт других участников. '''Раунд:''' 1. Расположить гангстеров в городе (большие кубики – «гангстеры – эксперты») они возвращаются обратно к игроку в конце раунда (если не были убиты, заключены под стражу или не попали в больницу). Маленькие кубики – «гангстеры- новички», в конце раунда не возвращаются. Чтобы выиграть карту города, ваших гангстеров в городе должно быть больше, чем у противников. 2. После расположения гангстеров в городе, вы должны обязательно выложить одну карту с вашей руки. На этом ваш ход заканчиватеся. Когда у каждого игрока остается по две карты на руках, открывается карта полиции. Игра заканчивается, если открыты карты полиции с тремя одинаковыми по цвету значками. ''Если вы выигрываете « пистолет», то ваш гангстер убит, если «решетка» – гангстер не участвует в игре в течение 2-ух раундов, если "больница"(красный крест) - гангстер не участвует в игре в течение 1 раунда. Если Вы получаете вычеркнутую карту человека в Цинциннати, вам запрещено располагать гангстеров в этом городе до конца игры.'' '''Карта Чикаго(Алькапоне).''' У Чикаго (Алькапоне) нет скрытой карты, вместо этого игрок, сыгравший гангстеров в Чикаго, делит выигрышные деньги из городов расположенных слева от него (Чикаго) и делит их с Алькапоне, с округлением в меньшую сторону. '''Подсказки новичкам.''' Гангстеров не обязательно выкладывать каждый раунд, обязательным является выложить карту города с вашей руки. Можно дождаться пока ваши противники начнут выкладывать карты с руки, чтобы понять, где можно заработать миллион. fda07a0572c0515408272f1bd3015ebe97a36b9f 423 419 2012-12-30T18:59:04Z Spacediver 718 reverted English back, moved Russian into corresponding separate page. wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space left each round. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. *If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. 216df9ddb16c37d4791196cf9503d42bd9c7b533 Gamehelpgomoku 0 81 422 2012-12-24T12:55:06Z Een 3 Created page with " == Goal == Create an unbroken row of exactly five stones of your color horizontally, vertically, or diagonally. Overlines (rows of 6 stones or more) do not count. == Vari..." wikitext text/x-wiki == Goal == Create an unbroken row of exactly five stones of your color horizontally, vertically, or diagonally. Overlines (rows of 6 stones or more) do not count. == Variant == In Gomoku+ (also named Caro) in order to win your row of five stones must be free at both ends. This balances the game differently and gives more defensive power to the white player. == Openings == Black always play first. With the 'standard' (free) opening, black has got a distinct advantage over white who is directly put 'under attack'. The 'tournament' opening aims to even the odds between the black and white players: * black lays the first stone at the center of the board * white lays the second stone in one of the spaces adjoining to the center of the board (horizontally, vertically or diagonally) * black lays the third stone at least three spaces away from the center of the board. 7a98f64e6b90bd76c2333efa14892ecb86a538ec Kaozeadenn Implijer:Sweetnaty 3 82 424 2012-12-30T19:01:39Z Spacediver 718 Перевод описания игры ;) wikitext text/x-wiki == Перевод описания игры ;) == Русский перевод описания игры нужно делать не поверх английского, который открывается отсюда: http://en.boardgamearena.com/#!gamepanel?game=theboss ...а на отдельной странице русского описания, куда ведет ссылка с '''русской версии''' сайта (обрати внимание на URL) http://ru.boardgamearena.com/#!gamepanel?game=theboss ca8e0ebb2778d155cb96b4f1de657321806eb7db Gamehelphawaii 0 34 425 101 2013-01-01T20:20:23Z Tobylongbeach 477 wikitext text/x-wiki Overview: You are the chieftain of a kingdom (your placemat) with up to five villages (rows). You buy or go to the islands to get place tiles that you put in your villages. There are five rounds and you get a decreasing amount of resources each round with which to acquire place tiles. Its a many-paths-to-victory kind of game. (It has been described as Stone Age without the dice). There are three kinds of resources: 1) Feet - let you move around the board, or travel to the islands or go to the cove to catch fish. 2) Clam shells - let you buy place tiles from the board 3) Fruit - can be used in place of feet or clam shells in all-or-nothing fashion. If you substitute for feet, you must substitute the entire moving cost. If you substitute for clams, you must substitute the entire purchase price. Moving: Your chieftains start at the beach and it costs nothing to return there from the board. Each movement in from the beach costs one foot. Moving up, down, right, left or diagonal on the board costs one foot per space. Staying on a space costs one foot. To go to the islands, you use your boats and feet. The closest island costs three feet and the farthest costs six. You have to have the feet as well as the space on the boats for the feet. You get an immediate victory point bonus for going to the islands but you do not get a price token (more about that later). Also, you get the level 2 version of whatever place tile or item you are getting on the islands. For instance, to go to the six foot island, you would need either: A) two three-feet boats and six feet resources or B) you would need the four-foot boat (which comes with a prepaid foot) and the two-foot boat as well as five feet resources. That is the advantage of the pre-paid foot on the four-foot boat. == Purchasing: == To buy some thing from the board: Select the price token (round colored circle with number inside) on the space with the place tile or item you want. If there is more than one place tile available on that space, you will be given a choice of which one you want. The movement cost will be in feet and the purchase price will be in clam shells but you can substitute either or both with fruit if you have it. You gain the price token for the round. There must be an available price token in order to purchase something from that space. You can pay double to get the level 2 version, which for most tiles is double effect. You place it in the village (row) of your choice. You must be able to place it in order to purchase it. A) You can only have one of each type of place tile in each village. For instance, you cannot have a foot (1) hut and a foot (2) hut in the same village but you can have a coconut fruit (1) tree and a breadfruit (2) tree in the same village. B) You can have only one god in each village. You can only have one of each type of god in your whole kingdom and the god vp effects are kingdom-wide. B) Each village must begin with a hut. The huts have a picture of a hut on them: foot hut, clam hut, spear hut, exchange hut, and long hut. ''' == Resources == ''' == Base reources == Base resources are on the round indicator. They decrease with each succeeding round. Everyone gets the base resources at the beginning of the round. Any unused resources can be used in the next round. == In-play resource bonuses == *The third, fourth and fifth villages give you 1, 2 and 3 clams respectively when you purchase Kahunas (Hawaiian priests) for them. *When you purchase for your kingdom the second, third and fourth Tikis, you are granted 1, 2, and 3 feet, respectively. *One or two of the island treasures are four fruit resources. == Resource Generators: == generate resources at the beginning of the next round. *Fruit level ones - one fruit *Fruit level twos - two fruit *Clam hut level one - one clam *Clam hut level two - two clams *Foot hut level one - one foot *Foot hut level two - two feet *Irrigation level two - one resource of your choice *Ku god - level one and two - one foot *Kane god level one - one clam *Kane god level two - two clams == Converter huts == Whenever you spend resources, a level 1 converter hut allows you to substitute one resource of your choice. So, for instance, you could move one space and buy something that has four price token on it with four fruit for the token and one clamshell being substituted for the one foot movement. Another example, you could go to the first island for two feet and one clamshell using a level 1 boat. The converter level 2 hut is the same but with any two resources. '''== Victory Points ==''' == In-play VP's: == *Going to the islands gives you a vp bonus. *Some of the treasures on the islands are 5 vp's. *Spear huts and the Ku god give you a bonus whenever you take a price token with crossed spears. Level 1 is 1 pt. bonus, Level 2 is two pt. bonus. == Round-End VP's: == There is a large sheild on the round indicator at the bottom. If the sum of price tokens and fish are greater than the number on the sheild, then you get a bonus. There is a large bonus for the player with highest sum score, a moderate bonus for the second highest and a token bonus for everyone else whose sum was greater than the sheild. Surfer place tiles lower the sheild value for qualifying for the bonus but surfers do not contribute to your sum when comparing to other players. Lono god level 1 gives you 2 vp's if you qualify for the bonus, and Lono god level 2 gives you 4 vp's if you qualify for the bonus == Game-End VP's: == A) Each village whose size does not extend to the Tikis is ignored for end-game scoring - its place tiles do not count and neither does its Kahuna. The villages below it are not affected - each village must reach the Kahunas independently. B) The Kahunas on the first, second, third, fourth and fifth villages scores the player five, five, ten, ten and fifteen points respectively. B) A hula dancer in a village scores one point for each place tile in her village including herself. A level 2 hula dancer scores two points instead of one for each place tile in her village including herself. C) Irrigation gives you pts for each type of fruit you have in that particular village: Breadfruit, guava, coconuts and bananas. D) The Long Hut level 2 is worth five points. The long hut level one just takes up space making it easier to reach the Kahunas but does not, itself, score points. E) The Laka god in your kingdom scores one pt for each fruit symbol on your place tiles in all of the villages which is the whole kingdom. Laka god level 2 scores two points for each fruit symbol. F) Kanaloa god scores two pts for each boat and each surfer on all the villages in the kingdom. Kanaloa 2 scores 4 pts for each boat and surfer. 5948df612fd3dc390051357ccb7e029823e4562b Browser support 0 13 426 69 2013-01-03T16:00:30Z Een 3 wikitext text/x-wiki [[Category:Help]] <h3>For the best experience, we recommend:</h3> * '''Google Chrome 10+''' [http://www.google.com/chrome Windows] [http://www.google.com/chrome?platform=mac Mac] [http://www.google.com/chrome?platform=linux Linux] * '''Mozilla Firefox 4+''' [http://www.mozilla.org/products/firefox/ Windows] [http://www.mozilla.org/products/firefox/ Mac] [http://www.mozilla.org/products/firefox/ Linux] Board Game Arena takes advantage of the most recent web technology to make it possible for you to play without installing anything on your computer: no software to download or update, no plugins to install, etc. Consequently, to play you need to use a modern web browser. Generally speaking, the more recent your web browser is, the more pleasant your game experience on Board Game Arena will be. This website makes intensive use of Javascript and your browser's graphics capabilities. Thus, if you want to have the best gaming experience with Board Game Arena, you should use one of the browsers listed above. However, we officially support the following browsers: * Google Chrome 4+ * Mozilla Firefox 3.5+ * Internet Explorer 9+ * Safari 4+ (Note: We do NOT support playing on iPads or similar tablets.) 82c74a446ab46ee91347f67d008b263af608ce10 Help 0 4 427 219 2013-01-05T09:30:25Z Sourisdudesert 1 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena]] ** [[About us]] ** [[Club Board Game Arena]] ** [[Contact us]] === Detailed help === * [[Getting started]] * [[Referral]] * [[Browser support]] * [[Moderation and grades]] * [[Game clock]] * [[Rating]] * [[Reputation]] * [[Translation guidelines]] c6067b5fc3f21568031e1b54885fd097134d4f1d How to join BGA developer team? 0 83 431 2013-01-05T09:46:40Z Sourisdudesert 1 Created page with " Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your player user name on BGA * your developer user name to b..." wikitext text/x-wiki Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your player user name on BGA * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, from time to time you will get by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum) <pre>NB: during the BETA pĥase, to smooth things up and make sure that everything is working correctly, we will work only with 3 fearless developers on 3 simple games.</pre> Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! e2db83f30a3fec64e81365b9198379fb7aaf63b7 Studio file reference 0 54 439 319 2013-01-05T10:11:33Z Sourisdudesert 1 /* states.inc.php */ wikitext text/x-wiki This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment. === 'img' directory === This directory contains the images for your game: * game_box.png is displayed on the main site on the game description page and when creating a table (280x280 px) * game_icon.png is the icon displayed in the lists of games and tables (50x50 px) * publisher.png is the logo of the publisher of the game, displayed on the game description page (width: 150 px) * and other images that you need. You should use [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites] for better web performance. === dbmodel.sql === File for creating specific database tables that you will need to persist data during the game (for example a table for cards). === gameoptions.inc.php === File for describing your game options (= game variants) === <gamename>.action.php === File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions. === <gamename>.css === CSS styles specific to your game. === <gamename>.game.php === This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. === <gamename>.js === This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. === <gamename>.view.php and <gamename>_<gamename>.tpl === Files used to set up the page layout ('view') for the game. === material.inc.php === File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants. === states.inc.php === This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). === stats.inc.php === File used to list statistics that you want to update during the game to be presented to players at the end of the game. 8c614009c3b9805382342cdc1cc704652e8f0897 Players actions (yourgamename.action.php) 0 84 440 2013-01-05T10:12:58Z Sourisdudesert 1 Created page with "=== APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $defaul..." wikitext text/x-wiki === APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false ) : Get script argument with the correct type : bCanFail means than a validation failure is possible (user input) : The main argType values are as follows. <pre> define( 'AT_int', 0 ); // an integer define( 'AT_posint', 1 ); // a positive integer define( 'AT_float', 2 ); // a float define( 'AT_email', 3 ); // an email define( 'AT_url', 4 ); // a URL define( 'AT_bool', 5 ); // 1/0/true/false define( 'AT_enum', 6 ); // argTypeDetails list the possible values define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space </pre> b249dbfc2f08f19e51c808b946b0ee96fbb467e6 Players actions: yourgamename.action.php 0 85 442 2013-01-05T10:14:07Z Sourisdudesert 1 Created page with "=== APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $defaul..." wikitext text/x-wiki === APP_GameAction class (<gamename>.action.php) === ; function isArg( $argName ) : Is this argument filled ? ; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false ) : Get script argument with the correct type : bCanFail means than a validation failure is possible (user input) : The main argType values are as follows. <pre> define( 'AT_int', 0 ); // an integer define( 'AT_posint', 1 ); // a positive integer define( 'AT_float', 2 ); // a float define( 'AT_email', 3 ); // an email define( 'AT_url', 4 ); // a URL define( 'AT_bool', 5 ); // 1/0/true/false define( 'AT_enum', 6 ); // argTypeDetails list the possible values define( 'AT_alphanum', 7 ); // only 0-9a-zA-Z_ and space </pre> b249dbfc2f08f19e51c808b946b0ee96fbb467e6 Studio function reference 0 55 443 392 2013-01-05T10:14:23Z Sourisdudesert 1 /* APP_GameAction class (.action.php) */ wikitext text/x-wiki This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to). This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below. == Server side (PHP functions) == === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value ; function DbQuery( $sql ) : Executes sql query on the database ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty. ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found : Raise an exception if more than 1 row is returned ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. == Client side (Javascript functions) == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 67089d3595e14018b2123d14b1494161851413cb 445 443 2013-01-05T10:14:52Z Sourisdudesert 1 /* Table class (.game.php) */ wikitext text/x-wiki This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to). This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below. == Server side (PHP functions) == === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. == Client side (Javascript functions) == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 44a0e60d2e0d37b86e80e3dd236f2f8fbe58c8fd 448 445 2013-01-05T10:16:23Z Sourisdudesert 1 /* Exceptions you can throw */ wikitext text/x-wiki This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to). This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below. == Server side (PHP functions) == == Client side (Javascript functions) == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 2a86068880a0d99bb4bbd5114e55f46dc395295c Main game logic: yourgamename.game.php 0 86 444 2013-01-05T10:14:46Z Sourisdudesert 1 Created page with "=== Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; functio..." wikitext text/x-wiki === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value ; function DbQuery( $sql ) : Executes sql query on the database ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty. ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found : Raise an exception if more than 1 row is returned ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row d6b0fc4adabe456d434028c91896088ba3d49559 446 444 2013-01-05T10:15:22Z Sourisdudesert 1 wikitext text/x-wiki === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value ; function DbQuery( $sql ) : Executes sql query on the database ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty. ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found : Raise an exception if more than 1 row is returned ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. cc95d4afc675e2d76a97502cc585135882ee4467 MediaWiki:Sidebar 8 2 447 2 2013-01-05T10:16:09Z Sourisdudesert 1 wikitext text/x-wiki * navigation ** http://boardgamearena.com|BoardGameArena.com ** mainpage|mainpage-description ** Studio|BGA Studio doc ** recentchanges-url|recentchanges * SEARCH * TOOLBOX * LANGUAGES c14629314b9ab77a3a7e98dd4e81d67ff8b7634e Game interface logic (yourgamename.js) 0 87 449 2013-01-05T10:16:36Z Sourisdudesert 1 Created page with "== Client side (Javascript functions) == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the t..." wikitext text/x-wiki == Client side (Javascript functions) == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 1e8dc993d4a1c11e472e5365ef1cd2b1e2306264 Studio 0 49 450 441 2013-01-05T10:17:16Z Sourisdudesert 1 /* BGA Studio documentation */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Game options and preferences: gameoptions.inc.php]] [[Studio function reference]] === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 62bbce3b9b3b136dadd05103b019629bcaac908f 452 450 2013-01-05T10:19:35Z Sourisdudesert 1 /* BGA Studio documentation */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Game options and preferences: gameoptions.inc.php]] === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 2e931b3065efa50525fe88c1fe3cb0780242e182 470 452 2013-01-11T12:06:01Z Sourisdudesert 1 /* BGA Studio documentation */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Game options and preferences: gameoptions.inc.php]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] c9cc10a2bb0d2ebc0e9a8423b365bf4d2c928557 Game interface logic: yourgamename.js 0 88 451 2013-01-05T10:17:58Z Sourisdudesert 1 Created page with "; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; thi..." wikitext text/x-wiki ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player f579fca77b6768cc083f8382df27a363a405db43 Studio file reference 0 54 453 439 2013-01-05T10:20:18Z Sourisdudesert 1 /* 'img' directory */ wikitext text/x-wiki This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment. === 'img' directory === This directory contains the images for your game. === dbmodel.sql === File for creating specific database tables that you will need to persist data during the game (for example a table for cards). === gameoptions.inc.php === File for describing your game options (= game variants) === <gamename>.action.php === File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions. === <gamename>.css === CSS styles specific to your game. === <gamename>.game.php === This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. === <gamename>.js === This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. === <gamename>.view.php and <gamename>_<gamename>.tpl === Files used to set up the page layout ('view') for the game. === material.inc.php === File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants. === states.inc.php === This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). === stats.inc.php === File used to list statistics that you want to update during the game to be presented to players at the end of the game. 2e7104613bcd7d665c1d222af10c97e42d262d56 454 453 2013-01-05T10:20:49Z Sourisdudesert 1 /* 'img' directory */ wikitext text/x-wiki This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment. === 'img' directory === This directory contains the images for your game (the game art). === dbmodel.sql === File for creating specific database tables that you will need to persist data during the game (for example a table for cards). === gameoptions.inc.php === File for describing your game options (= game variants) === <gamename>.action.php === File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions. === <gamename>.css === CSS styles specific to your game. === <gamename>.game.php === This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. === <gamename>.js === This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. === <gamename>.view.php and <gamename>_<gamename>.tpl === Files used to set up the page layout ('view') for the game. === material.inc.php === File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants. === states.inc.php === This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). === stats.inc.php === File used to list statistics that you want to update during the game to be presented to players at the end of the game. d8bd4830bfb0b86dcdf637549a560f991d2667ba Game art: img directory 0 89 455 2013-01-05T10:38:20Z Sourisdudesert 1 Created page with "== Requested images == The following images are requested by BGA: ;game_box.png * It is displayed on the main site on the game description page and when creating a table (28..." wikitext text/x-wiki == Requested images == The following images are requested by BGA: ;game_box.png * It is displayed on the main site on the game description page and when creating a table (280x280 px). * It should be an image of a physical copy of the game box as it appears in an online shop. * It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game. * The background of the image must be transparent. ;game_icon.png * It is the icon displayed in the lists of games and tables (50x50 px). * This one should not be transparent, and shouldn't have a border (a black border will be add by BGA). * The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title). ;publisher.png * It is the logo of the publisher of the game, displayed on the game description page. * The width must be 150 px. The height can be anything. The image could be transparent. == Game art == You must upload in img directory all images of your game interface. === Images loading === '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. Note that you can tune the way images are loaded with Javascript methods "dontPreloadImage" and "ensureSpecificImageLoading" (see [[Game_interface_logic:_yourgamename.js]]). === Images format === You can use 3 image format while building your game interface: ;jpg images should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load. ;png images should be used for transparent images. ;gif images can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful. * and other images that you need. You should use [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites] for better web performance. 1dc31974112f183a7fcaed36d1d945a3cc155fd2 456 455 2013-01-05T10:38:52Z Sourisdudesert 1 /* Images loading */ wikitext text/x-wiki == Requested images == The following images are requested by BGA: ;game_box.png * It is displayed on the main site on the game description page and when creating a table (280x280 px). * It should be an image of a physical copy of the game box as it appears in an online shop. * It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game. * The background of the image must be transparent. ;game_icon.png * It is the icon displayed in the lists of games and tables (50x50 px). * This one should not be transparent, and shouldn't have a border (a black border will be add by BGA). * The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title). ;publisher.png * It is the logo of the publisher of the game, displayed on the game description page. * The width must be 150 px. The height can be anything. The image could be transparent. == Game art == You must upload in img directory all images of your game interface. === Images loading === '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. Note that you can tune the way images are loaded with Javascript methods "dontPreloadImage" and "ensureSpecificImageLoading" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]). === Images format === You can use 3 image format while building your game interface: ;jpg images should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load. ;png images should be used for transparent images. ;gif images can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful. * and other images that you need. You should use [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites] for better web performance. a4fe8df99a6159ca229086d9623e012f0d009063 457 456 2013-01-05T10:41:44Z Sourisdudesert 1 /* Game art */ wikitext text/x-wiki == Requested images == The following images are requested by BGA: ;game_box.png * It is displayed on the main site on the game description page and when creating a table (280x280 px). * It should be an image of a physical copy of the game box as it appears in an online shop. * It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game. * The background of the image must be transparent. ;game_icon.png * It is the icon displayed in the lists of games and tables (50x50 px). * This one should not be transparent, and shouldn't have a border (a black border will be add by BGA). * The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title). ;publisher.png * It is the logo of the publisher of the game, displayed on the game description page. * The width must be 150 px. The height can be anything. The image could be transparent. == Game art == You must upload in img directory all images of your game interface. === Images loading === '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. Note that you can tune the way images are loaded with Javascript methods "dontPreloadImage" and "ensureSpecificImageLoading" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]). === Images format === You can use 3 image format while building your game interface: ;jpg images should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load. ;png images should be used for transparent images. ;gif images can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful. === Use CSS Sprites === To limit the number of images load and make the game load faster, you must use CSS sprites, ie you must gather several images in a single one. To learn more on CSS Sprites: * [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites (W3C documentation)]. * [[Game interface stylesheet: yourgamename.css]] 0784d5f20fdd5fdc96ac6f303ff161afe79a2d9a 458 457 2013-01-05T10:43:51Z Sourisdudesert 1 /* Requested images */ wikitext text/x-wiki == Requested images == The following images are requested by BGA: ;game_box.png * It is displayed on the main site on the game description page and when creating a table (280x280 px). * It should be an image of a physical copy of the game box as it appears in an online shop. * It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game. * The background of the image must be transparent. ;game_icon.png * It is the icon displayed in the lists of games and tables (50x50 px). * This one should not be transparent, and shouldn't have a border (a black border will be add by BGA). * The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title). ;publisher.png * It is the logo of the publisher of the game, displayed on the game description page. * The width must be 150 px. The height can be anything. The image could be transparent. ;publisher2.png (optional) * If the game has been co-published by 2 publishers, you should upload a second image named "publisher2.png" (same characteristic than the first one). == Game art == You must upload in img directory all images of your game interface. === Images loading === '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. Note that you can tune the way images are loaded with Javascript methods "dontPreloadImage" and "ensureSpecificImageLoading" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]). === Images format === You can use 3 image format while building your game interface: ;jpg images should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load. ;png images should be used for transparent images. ;gif images can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful. === Use CSS Sprites === To limit the number of images load and make the game load faster, you must use CSS sprites, ie you must gather several images in a single one. To learn more on CSS Sprites: * [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites (W3C documentation)]. * [[Game interface stylesheet: yourgamename.css]] d01797346a998de4ef982255fe6e442d5ac27e44 Main game logic: yourgamename.game.php 0 86 459 446 2013-01-05T10:51:52Z Sourisdudesert 1 wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value ; function DbQuery( $sql ) : Executes sql query on the database ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for the sql query. First column must be a primary or alternate key. The resulting collection can be empty. ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found : Raise an exception if more than 1 row is returned ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 2e0422c01375873d889cd852153941009f5dee2c 460 459 2013-01-05T11:06:45Z Sourisdudesert 1 wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; function DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" <pre> Example 1: self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) Example 2: self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0' ), 1235 => 'myuser1' ) ) </pre> ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model. === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. fd806d41060480c3e3ad5ff086652fbc30b52eea 461 460 2013-01-05T11:07:26Z Sourisdudesert 1 /* Accessing database */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; function DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; function getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; function getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0' ), 1235 => 'myuser1' ) ) </pre> ; protected function getNonEmptyCollectionFromDB( $sql ) : Idem, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql query as an associative array or null if there is no result : Raise an exception if the query return more than one row ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model. === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 86bb80f233b8a2c1bced9630000c454879ac6000 462 461 2013-01-05T11:10:05Z Sourisdudesert 1 /* Accessing database */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model. === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. e0229a8a72f18d407c46e8f9b0f6ced331099012 463 462 2013-01-05T11:10:28Z Sourisdudesert 1 /* Accessing database */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model. === Table class (<gamename>.game.php) === ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) ; function getPlayersNumber() : Returns the number of players playing at the table ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value === Exceptions you can throw === ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 755a3c27dc759d73a4c99b8e9b888c680c3350d1 464 463 2013-01-05T11:15:56Z Sourisdudesert 1 wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; function getPlayersNumber() : Returns the number of players playing at the table ; function getActivePlayerId() : Get the "active_player", whatever what is the current state type : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated. It is not always the active player. ; function getCurrentPlayerName() : Get the "current_player" name ; function getCurrentPlayerColor() : Get the "current_player" color ; function isCurrentPlayerZombie() : Check the "current_player" zombie status == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model. == Game states and active players == ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 417c04fb7af0bff492989ae695f4f345a37c52e4 465 464 2013-01-05T11:19:55Z Sourisdudesert 1 /* Accessing player informations */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; function getActivePlayerName() : Get the "active_player" name ; function getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; function getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; function getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; function isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model. == Game states and active players == ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. b4e9344ba235bca69d92731c2f926fbeb2959325 466 465 2013-01-05T11:23:52Z Sourisdudesert 1 /* Accessing player informations */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : TODO ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model. == Game states and active players == ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 2d204c8553c8d00246f0efaab8c18e8a447179e5 467 466 2013-01-10T16:57:45Z Pikiou 1872 /* Accessing player informations */ alternative for getPlayersNumber in setupNewGame wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : TODO ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model. == Game states and active players == ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 013a1ae0c029d6b1be62ea12e8269bbe471a6ccd 468 467 2013-01-11T11:48:42Z Sourisdudesert 1 wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : TODO ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model. == Game states and active players == ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 92a6616477137f9c24f2625d6ca7f4c362b5c522 469 468 2013-01-11T11:51:35Z Sourisdudesert 1 /* Accessing player informations */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model. == Game states and active players == ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 8319df29226e7701f278f183dfafd66173d508ce 487 469 2013-01-11T14:18:47Z Sourisdudesert 1 /* Accessing player informations */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model. == Game states and active players == ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function activeNextPlayer() : Make the next player active ; function activePrevPlayer() : Make the previous player active == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. d1370aa7c9c631a4b646a39a8b9a3232b9202c2a 488 487 2013-01-11T14:22:33Z Sourisdudesert 1 /* Game states and active players */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see [[Editing Game database model: dbmodel.sql]] to know how to define your database model. == Game states and active players == ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; function activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 8ea47e5ee7ae9faad7a436fc0ba0812140c00fb4 491 488 2013-01-11T14:41:59Z Sourisdudesert 1 /* Accessing database */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Game states and active players == ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; function activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 0f0aee686502df2f0e731c6f48979a9e608eb757 498 491 2013-01-11T15:33:44Z Sourisdudesert 1 /* Accessing database */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; function DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; function DbAffectedRow() : Return the number of row affected by the last operation ; function escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Game states and active players == ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; function activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. f5a3c57d55530f819dccea62b703ca23316dd8af 499 498 2013-01-11T15:42:31Z Sourisdudesert 1 /* Accessing database */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Game states and active players == ; function checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception ; function activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; function activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 3837cd00d2194d98c93a777e1a61827da5feec9b Your game state machine: states.inc.php 0 90 471 2013-01-11T13:19:50Z Sourisdudesert 1 Created page with " This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the..." wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === Game state ID === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). 64db0b4c31e2f6372cd2819e12291f99087f1d58 472 471 2013-01-11T13:24:31Z Sourisdudesert 1 /* Syntax */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === Game state ID === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). === Game state name === (mandatory) The name of a game state is used to identify it in your game logic. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> 122046b59cce388a4eb0e91e6b1ee6ef5669b9f9 473 472 2013-01-11T13:24:58Z Sourisdudesert 1 /* Game state name */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === Game state ID === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). === Game state name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> 2807b405f3ea0817378ad5eea0e0e6019aff05dc 474 473 2013-01-11T13:39:01Z Sourisdudesert 1 /* Syntax */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> == description == (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "arg" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. == descriptionmyturn == 984ab22f16888cc5be11c4feefebe2f1cb87832f 475 474 2013-01-11T13:43:11Z Sourisdudesert 1 /* descriptionmyturn */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> == description == (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "arg" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. == descriptionmyturn == (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. c71d493e9411d9543bfdc4e12064b01331340977 476 475 2013-01-11T13:43:42Z Sourisdudesert 1 /* description */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "arg" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. == descriptionmyturn == (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. 90f150994f2c80467670000ba070796d005fc402 477 476 2013-01-11T13:43:48Z Sourisdudesert 1 /* descriptionmyturn */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "arg" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. 9be143bed66f07c9026f63c1d288e56f45502de9 478 477 2013-01-11T13:45:32Z Sourisdudesert 1 /* Syntax */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "arg" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. 8a60a37723221c9a982b73cb792a1a9ed9a8eabd 479 478 2013-01-11T13:51:07Z Sourisdudesert 1 /* descriptionmyturn */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "arg" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". e53759ccf506d389b182eb85ab80aa719bc7599c 480 479 2013-01-11T13:52:11Z Sourisdudesert 1 /* id */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "arg" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". 0f7c457ab6a3eacff262fd685514839a3fa65e8b 481 480 2013-01-11T13:52:19Z Sourisdudesert 1 /* id */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "arg" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". c42e3bcd700318400aafdc3b1e13b1afe4bdd309 482 481 2013-01-11T14:02:57Z Sourisdudesert 1 /* action */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "arg" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> 6350bda2becff3188000260128af9be79098886d 483 482 2013-01-11T14:07:59Z Sourisdudesert 1 /* transitions */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "arg" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) { return ; } .... </pre> a60bd8c9f68bcf0ec45770c0f3a5b39cf652b9f0 484 483 2013-01-11T14:08:14Z Sourisdudesert 1 /* possibleactions */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "arg" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> a54b5a8b71b94de9489c426b6e3e7f8d8c17399b 485 484 2013-01-11T14:13:58Z Sourisdudesert 1 /* possibleactions */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "arg" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> === args === (optional) From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state. Example 1 : for Reversi, the list of possible moves during playerTurn state. Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor. Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them. In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them. Thus, this data can be transmitted to the clients and used by the clients to display it. Let's see a complete example using args with « Reversi » game : In states.inc.php, we specify some « args » argument for gamestate « playerTurn » : <pre> 10 => array( "name" => "placeWorkers", "description" => clienttranslate('${actplayer} must place some workers'), "descriptionmyturn" => clienttranslate('${you} must place some workers'), "type" => "activeplayer", '''"args" => "argPlaceWorkers",''' "possibleactions" => array( "placeWorkers" ), "transitions" => array( "nextPlayer" => 11, "nextPhase" => 12, "zombiePass" => 11 ) ), </pre> === updateGameProgression === (optional) IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated. At least one of your game state (any of them) must specify updateGameProgression=>true. ab7a9a311b70804a2341683b23ee13310f5b188f 486 485 2013-01-11T14:16:16Z Sourisdudesert 1 /* args */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "arg" PHP method (see below "arg" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "arg" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> === args === (optional) From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state. Example 1 : for Reversi, the list of possible moves during playerTurn state. Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor. Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them. In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them. Thus, this data can be transmitted to the clients and used by the clients to display it. Let's see a complete example using args with « Reversi » game : In states.inc.php, we specify some « args » argument for gamestate « playerTurn » : <pre> 10 => array( "name" => "placeWorkers", "description" => clienttranslate('${actplayer} must place some workers'), "descriptionmyturn" => clienttranslate('${you} must place some workers'), "type" => "activeplayer", "args" => "argPlaceWorkers", <================================== HERE "possibleactions" => array( "placeWorkers" ), "transitions" => array( "nextPlayer" => 11, "nextPhase" => 12, "zombiePass" => 11 ) ), </pre> It corresponds to a « argPlaceWorkers » method in our PHP code (reversi.game.php): <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves() ); } </pre> Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn : <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> Note: you can also used values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above). Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn). === updateGameProgression === (optional) IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated. At least one of your game state (any of them) must specify updateGameProgression=>true. 1cbe5d759b0e2ab2ccc6de088662afa6e71c75b6 Game database model: dbmodel.sql 0 92 490 2013-01-11T14:41:22Z Sourisdudesert 1 Created page with "In this file you specify the database schema of your game. This file contains SQL queries that will be executed during the creation of your game table. Note: you can't chang..." wikitext text/x-wiki In this file you specify the database schema of your game. This file contains SQL queries that will be executed during the creation of your game table. Note: you can't change the database schema during the game. == Create your schema == To build this file, we recommend you to build the tables you need with the PhpMyAdmin tool (see BGA user guide), and then to export them and to copy/paste the content inside this file. == Default tables == Important: by default, BGA creates 4 tables for your game: global, stats, gamelog, and player. You must not modify the schema of global, stats and gamelog tables (and you must not access them directly with SQL queries in your PHP code). You may add columns to "player" table. This is very practical to add simple values associated with players. Example: <pre> ALTER TABLE `player` ADD `player_reserve_size` SMALLINT UNSIGNED NOT NULL DEFAULT '7'; </pre> For your information, the useful columns of default "player" table are: * player_no: the index of player in natural playing order. * player_id * player_name: (note: you should better access this date with getActivePlayerName() or loadPlayersBasicInfos() methods) * player_score: the current score of the player (displayed in the player panel). You must update this field to update player's scores. * player_score_aux: the secondary score, used as a tie breaker. You must update this field according to tie breaking rules of the game. 2a8820a0ff219470e0d437ff49a161ce7e12ae0f Players actions: yourgamename.action.php 0 85 492 442 2013-01-11T14:56:04Z Sourisdudesert 1 wikitext text/x-wiki == Purpose of this file == With this file, you define all the players entry points (ie: possible game actions) of your game. This file is a sort of "bridge" between the AJAX calls you are doing from your Javascript client side, and your main PHP code in "yourgame.game.php". The role of the methods defined in this file is to filter the arguments, eventually to format them a little bit, and then to call a corresponding PHP method from your main game logic ("yourgame.game.php" file). Methods in this file must be short: no game logic must be introduced here. == Example of typical action method == (from Reversi example) <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> == Methods to use in action methods == ; function setAjaxMode : Must be use at the beginning of each action method. ; function ajaxResponse : Must be use at the end of each action method. ; function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false ) : This method must be used to retrieve the arguments sent with your AJAX query. : You must NOT use "_GET", "_POST" or equivalent PHP variables to do this, as it is unsafe. : This method use the following arguments: : * argName: the name of the argument to retrieve. : * argType: the type of the argument. You should use one of the following: : 'AT_int' for an integer : 'AT_posint' for a positive integer : 'AT_float' for a float : 'AT_bool' for 1/0/true/false : 'AT_enum' for an enumeration (argTypeDetails list the possible values as an array) : 'AT_alphanum' for a string with 0-9a-zA-Z_ and space : bCanFail means than a validation failure is possible (user input) : The main argType values are as follows. <pre> ; function isArg( $argName ) : Return "true" or "false" whether "argName" has been specified as an argument of the AJAX request or not. </pre> 8c4f55762d427d4ec9ec448bb25c0a942246d00f 493 492 2013-01-11T14:58:20Z Sourisdudesert 1 /* Methods to use in action methods */ wikitext text/x-wiki == Purpose of this file == With this file, you define all the players entry points (ie: possible game actions) of your game. This file is a sort of "bridge" between the AJAX calls you are doing from your Javascript client side, and your main PHP code in "yourgame.game.php". The role of the methods defined in this file is to filter the arguments, eventually to format them a little bit, and then to call a corresponding PHP method from your main game logic ("yourgame.game.php" file). Methods in this file must be short: no game logic must be introduced here. == Example of typical action method == (from Reversi example) <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> == Methods to use in action methods == '''function setAjaxMode''' Must be use at the beginning of each action method. '''function ajaxResponse''' Must be use at the end of each action method. '''function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )''' This method must be used to retrieve the arguments sent with your AJAX query. You must NOT use "_GET", "_POST" or equivalent PHP variables to do this, as it is unsafe. This method use the following arguments: * argName: the name of the argument to retrieve. * argType: the type of the argument. You should use one of the following: 'AT_int' for an integer 'AT_posint' for a positive integer 'AT_float' for a float 'AT_bool' for 1/0/true/false 'AT_enum' for an enumeration (argTypeDetails list the possible values as an array) 'AT_alphanum' for a string with 0-9a-zA-Z_ and space 'AT_numberlist' for a list of several numbers separated with "," or ";" (ex: exemple: 1,4;2,3;-1,2). bCanFail means than a validation failure is possible (user input) The main argType values are as follows. '''function isArg( $argName )''' Return "true" or "false" whether "argName" has been specified as an argument of the AJAX request or not. </pre> a19d6dfedf8fe2277f7069fe3b0a5a9c9a7646dd 494 493 2013-01-11T15:03:50Z Sourisdudesert 1 /* Methods to use in action methods */ wikitext text/x-wiki == Purpose of this file == With this file, you define all the players entry points (ie: possible game actions) of your game. This file is a sort of "bridge" between the AJAX calls you are doing from your Javascript client side, and your main PHP code in "yourgame.game.php". The role of the methods defined in this file is to filter the arguments, eventually to format them a little bit, and then to call a corresponding PHP method from your main game logic ("yourgame.game.php" file). Methods in this file must be short: no game logic must be introduced here. == Example of typical action method == (from Reversi example) <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> == Methods to use in action methods == '''function setAjaxMode''' Must be use at the beginning of each action method. '''function ajaxResponse''' Must be use at the end of each action method. '''function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )''' This method must be used to retrieve the arguments sent with your AJAX query. You must NOT use "_GET", "_POST" or equivalent PHP variables to do this, as it is unsafe. This method use the following arguments: * argName: the name of the argument to retrieve. * argType: the type of the argument. You should use one of the following: 'AT_int' for an integer 'AT_posint' for a positive integer 'AT_float' for a float 'AT_bool' for 1/0/true/false 'AT_enum' for an enumeration (argTypeDetails list the possible values as an array) 'AT_alphanum' for a string with 0-9a-zA-Z_ and space 'AT_numberlist' for a list of several numbers separated with "," or ";" (ex: exemple: 1,4;2,3;-1,2). * mandatory: specify "true" if the argument is mandatory. * default: if mandatory=false, you can specify here a default value in case the argument is not present. * argTypeDetails: see AT_enum above. * bCanFail: if true, specify that it may be possible that the argument won't be of the type specified by argType (and then do not log this as a fatal error in the system, and return a standard exception to the player). '''function isArg( $argName )''' This is a useful method when you only want to check if an argument is present or not present in your AJAX request (and don't care of the value. It returns "true" or "false" whether "argName" has been specified as an argument of the AJAX request or not. 46067eef7c4401ee68e1c3a4512ab090091e4c1d 495 494 2013-01-11T15:07:01Z Sourisdudesert 1 /* Methods to use in action methods */ wikitext text/x-wiki == Purpose of this file == With this file, you define all the players entry points (ie: possible game actions) of your game. This file is a sort of "bridge" between the AJAX calls you are doing from your Javascript client side, and your main PHP code in "yourgame.game.php". The role of the methods defined in this file is to filter the arguments, eventually to format them a little bit, and then to call a corresponding PHP method from your main game logic ("yourgame.game.php" file). Methods in this file must be short: no game logic must be introduced here. == Example of typical action method == (from Reversi example) <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> == Methods to use in action methods == '''function setAjaxMode''' Must be use at the beginning of each action method. '''function ajaxResponse''' Must be use at the end of each action method. '''function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )''' This method must be used to retrieve the arguments sent with your AJAX query. You must NOT use "_GET", "_POST" or equivalent PHP variables to do this, as it is unsafe. This method use the following arguments: * argName: the name of the argument to retrieve. * argType: the type of the argument. You should use one of the following: 'AT_int' for an integer 'AT_posint' for a positive integer 'AT_float' for a float 'AT_bool' for 1/0/true/false 'AT_enum' for an enumeration (argTypeDetails list the possible values as an array) 'AT_alphanum' for a string with 0-9a-zA-Z_ and space 'AT_numberlist' for a list of several numbers separated with "," or ";" (ex: exemple: 1,4;2,3;-1,2). * mandatory: specify "true" if the argument is mandatory. * default: if mandatory=false, you can specify here a default value in case the argument is not present. * argTypeDetails: see AT_enum above. * bCanFail: if true, specify that it may be possible that the argument won't be of the type specified by argType (and then do not log this as a fatal error in the system, and return a standard exception to the player). '''function isArg( $argName )''' This is a useful method when you only want to check if an argument is present or not present in your AJAX request (and don't care of the value. It returns "true" or "false" whether "argName" has been specified as an argument of the AJAX request or not. == Useful tip: retrieve a list of number == If your Javascript send a list of integer separated by ";" (ex: "1;2;3;4") as an argument, you can transform them in a PHP array with the following: <pre> public function playCards() { self::setAjaxMode(); $card_ids_raw = self::getArg( "card_ids", AT_numberlist, true ); // Removing last ';' if exists if( substr( $card_ids_raw, -1 ) == ';' ) $card_ids_raw = substr( $card_ids_raw, 0, -1 ); if( $card_ids_raw == '' ) $card_ids = array(); else $card_ids = explode( ';', $card_ids_raw ); $this->game->playCards( $card_ids ); self::ajaxResponse( ); } </pre> bae1cc6ec52c6feadc80d3bd3e4aa03ff95908b8 Game material description: material.inc.php 0 93 496 2013-01-11T15:18:46Z Sourisdudesert 1 Created page with "This PHP file describes all the material of your game. This file is include by the constructor of your main game logic (yourgame.game.php), and then the variables defined her..." wikitext text/x-wiki This PHP file describes all the material of your game. This file is include by the constructor of your main game logic (yourgame.game.php), and then the variables defined here are accessible everywhere in your game logic file. Example from "Hearts": if you define this in material.inc.php: <pre> $this->colors = array( 1 => array( 'name' => clienttranslate('spade'), 'nametr' => self::_('spade') ), 2 => array( 'name' => clienttranslate('heart'), 'nametr' => self::_('heart') ), 3 => array( 'name' => clienttranslate('club'), 'nametr' => self::_('club') ), 4 => array( 'name' => clienttranslate('diamond'), 'nametr' => self::_('diamond') ) ); </pre> ... you can access "$this->colors" everywhere in your PHP game logic file. 076a3890e55f1fa9e5466f29cde040c46ffe67c0 497 496 2013-01-11T15:23:52Z Sourisdudesert 1 wikitext text/x-wiki This PHP file describes all the material of your game. This file is include by the constructor of your main game logic (yourgame.game.php), and then the variables defined here are accessible everywhere in your game logic file. Using material.inc.php makes your PHP logic file smaller and clean. Example from "Hearts": if you define this in material.inc.php: <pre> $this->colors = array( 1 => array( 'name' => clienttranslate('spade'), 'nametr' => self::_('spade') ), 2 => array( 'name' => clienttranslate('heart'), 'nametr' => self::_('heart') ), 3 => array( 'name' => clienttranslate('club'), 'nametr' => self::_('club') ), 4 => array( 'name' => clienttranslate('diamond'), 'nametr' => self::_('diamond') ) ); </pre> ... you can access "$this->colors" everywhere in your PHP game logic file. e7a93d7e58d52c2a8bef0f954da5a495b33020f5 Main game logic: yourgamename.game.php 0 86 500 499 2013-01-11T15:44:56Z Sourisdudesert 1 /* Game states and active players */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; function activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; function activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. b71dd97bac1bd6a6e4f272c0e71c0c642f6f682c 504 500 2013-01-11T15:47:57Z Sourisdudesert 1 /* Translations */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; function activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; function activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == See [[Translations]] == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 852a46f013f70307a38382fd2ee5c3d0d18c797e 505 504 2013-01-11T15:49:19Z Sourisdudesert 1 /* Accessing database */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Using globals == == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; function activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; function activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == See [[Translations]] == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 8d73b6994cd02253b43a940b0d520f77233a8f8c 506 505 2013-01-11T15:58:07Z Sourisdudesert 1 /* Using globals */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; function activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; function activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == See [[Translations]] == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 636e63e3bc63774d2554983bed02eb9b115cf506 508 506 2013-01-11T16:03:04Z Sourisdudesert 1 /* Game states and active players */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; function activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; function activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Players turn order == '''createNextPlayerTable( $players, $bLoop=true )''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> $players = self::loadPlayersBasicInfos() $nextPlayers = createNextPlayerTable( $players ); // return array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); $nextPlayers = createNextPlayerTable( $players, false ); // return array( 1 => 2, 2 => 3, 0 => 1 ); </pre> == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == See [[Translations]] == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 1d8d43d07f3ec3d264df38a6db890b7754487155 509 508 2013-01-11T16:06:05Z Sourisdudesert 1 /* Players turn order */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; function activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; function activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == See [[Translations]] == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 5cda35c29ef2339660b1b9ef0cac8c40f36762c1 510 509 2013-01-11T16:06:52Z Sourisdudesert 1 /* Players turn order */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; function activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; function activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == See [[Translations]] == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player (standard extra time is a game option) == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 08c40fe97a1b285f7b648813931d0f4fed42c8d4 511 510 2013-01-11T16:08:42Z Sourisdudesert 1 /* Reflexion time */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; function activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; function activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == == Game statistics == ; function initStat( $table_or_player, $name, $value, $player_id=null ) : Create a statistic entry for the specified statistics with a default value : In case of a "player" entry, if player_id is not specified, all players are set to the same value ; function setStat( $value, $name, $player_id = null ) : Set statistic value ; function incStat( $delta, $name, $player_id = null ) : Increment (or decrement) specified value == Translations == See [[Translations]] == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. b916b96471dd091a82c47c1a595813f6813fe122 513 511 2013-01-11T16:15:56Z Sourisdudesert 1 /* Game statistics */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; function activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; function activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 30e4fbe4a7a9f3484375ac3e49c4de8ffb430c28 514 513 2013-01-11T16:24:11Z Sourisdudesert 1 /* Notify players */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; function activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; function activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. c736610fc329a786629ddf77ed3612ca3a6e0400 515 514 2013-01-11T16:26:41Z Sourisdudesert 1 /* Notify players */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; function activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; function activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 64e2d717a68cd4e452a230b8dd290fc7c24a1779 516 515 2013-01-11T16:29:48Z Sourisdudesert 1 /* Game states and active players */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 0c9f99bbd1eec9cc35913e05464c1cab169d9918 517 516 2013-01-11T16:38:09Z Sourisdudesert 1 /* Game states and active players */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. ; throw new BgaSystemVisibleException ( $error_message) : Same as previous, except that the message is visible by the user. You can use this if the message is understandable by the user. 3602613dae96f6572bb8b2b05719baaf61a71a93 518 517 2013-01-11T16:45:57Z Sourisdudesert 1 /* Managing errors and exceptions */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. 7669befb882381077e8b9eead19707ff5f3d32b6 Studio 0 49 501 470 2013-01-11T15:47:24Z Sourisdudesert 1 /* Other components */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 0b06c55548d666ef11e610ff3549d651ed1dafa2 529 501 2013-01-14T20:17:28Z Een 3 /* How to join BGA developer team? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 7e6d5b482e09c3b7b35b48a1b07e9ecd44c62b61 Translations 0 94 502 2013-01-11T15:47:33Z Sourisdudesert 1 Created page with " (todo)" wikitext text/x-wiki (todo) 5d301b12a9331eb33c9c5d7c0fa41fb6c5d4ba56 503 502 2013-01-11T15:47:46Z Sourisdudesert 1 wikitext text/x-wiki ; function _( $text ) : Transparent function, used to mark strings to be translated on the server side (ex: error message) ; function clienttranslate( $string ) : Transparent function: used to mark string to be translated on client side (ex: notification message) 24c00b9c260eebd9acf6ee6ac66fb2fb049781c3 530 503 2013-01-15T16:55:04Z Sourisdudesert 1 wikitext text/x-wiki Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them. == How translation works? == When developing your game, all strings must be in English. Strings must be coherent with the English version of the game. Before the release of the game, BGA team will do the French translation of the game. After the release of the game, the BGA players community will translate the game in every language. == What should be translated? == Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ... This does NOT include error messages that are not supposed to happened (unexpected errors). == Focus on translating notifications == Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function. However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side. == On client side (Javascript) == On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate. Examples: <pre> // Get a string in player's language: var translated = _("original english string"); // Get a string in player's language with parameter: var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", { p: 2, d: 4 } ); </pre> Note: what is also possible to do is == On server side (PHP) == On PHP side, you can use 3 different functions to specify that a string must be translated. '''clienttranslate( "my string to translate" ):''' This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side. In general, you use clienttranslate: * On your states.inc.php, for field "description" and "descriptionmyturn". * On "material.inc.php", when defining texts for game material that must be displayed on client side. * When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation. '''self::_( "my string to translate" ):''' This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player). Most of the time, you don't need to translate strings on server side, except on the following 3 situations: * When throwing an exception because the player did a forbidden move. * In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file. * Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions. * Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user. 7faacf163abbdcae5aa87a9f68ef1964d1c12b63 531 530 2013-01-15T16:57:24Z Sourisdudesert 1 /* On server side (PHP) */ wikitext text/x-wiki Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them. == How translation works? == When developing your game, all strings must be in English. Strings must be coherent with the English version of the game. Before the release of the game, BGA team will do the French translation of the game. After the release of the game, the BGA players community will translate the game in every language. == What should be translated? == Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ... This does NOT include error messages that are not supposed to happened (unexpected errors). == Focus on translating notifications == Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function. However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side. == On client side (Javascript) == On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate. Examples: <pre> // Get a string in player's language: var translated = _("original english string"); // Get a string in player's language with parameter: var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", { p: 2, d: 4 } ); </pre> Note: what is also possible to do is == On server side (PHP) == On PHP side, you can use 3 different functions to specify that a string must be translated. '''clienttranslate( "my string to translate" ):''' This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side. In general, you use clienttranslate: * On your states.inc.php, for field "description" and "descriptionmyturn". * On "material.inc.php", when defining texts for game material that must be displayed on client side. * When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation. '''self::_( "my string to translate" ):''' This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player). Most of the time, you don't need to translate strings on server side, except on the following 3 situations: * When throwing an exception because the player did a forbidden move. * In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file. * Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions. * Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user. '''totranslate( "my string to translate" ):''' This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side. You should not use this function, except on the following cases: * Statistics name in stats.inc.php * Option names and option values name in gameoptions.inc.php aef6fc156d64ae4fb1e6e7bcdc3e4b83b5165666 532 531 2013-01-15T17:03:59Z Sourisdudesert 1 /* On server side (PHP) */ wikitext text/x-wiki Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them. == How translation works? == When developing your game, all strings must be in English. Strings must be coherent with the English version of the game. Before the release of the game, BGA team will do the French translation of the game. After the release of the game, the BGA players community will translate the game in every language. == What should be translated? == Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ... This does NOT include error messages that are not supposed to happened (unexpected errors). == Focus on translating notifications == Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function. However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side. == On client side (Javascript) == On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate. Examples: <pre> // Get a string in player's language: var translated = _("original english string"); // Get a string in player's language with parameter: var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", { p: 2, d: 4 } ); </pre> Note: what is also possible to do is == On server side (PHP) == On PHP side, you can use 3 different functions to specify that a string must be translated. '''clienttranslate( "my string to translate" ):''' This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side. In general, you use clienttranslate: * On your states.inc.php, for field "description" and "descriptionmyturn". <pre> "description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'), </pre> * On "material.inc.php", when defining texts for game material that must be displayed on client side. <pre> $this->card_types = array( 1 => array( 'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side. </pre> * When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation. <pre> // A game log string with no argument: self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() ); </pre> '''self::_( "my string to translate" ):''' This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player). Most of the time, you don't need to translate strings on server side, except on the following 3 situations: * When throwing an exception because the player did a forbidden move. <pre> // This will display a translatable red message to the player that just do some wrong action: throw new feException( self::_('You must choose 3 cards'), true); // ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated. </pre> * In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file. * Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions. <pre> // In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this: throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true ); </pre> * Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user. '''totranslate( "my string to translate" ):''' This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side. You should not use this function, except on the following cases: * Statistics name in stats.inc.php * Option names and option values name in gameoptions.inc.php 519d1b8d8f83dc3f8ef485ff25657a06063da52e 533 532 2013-01-15T17:04:47Z Sourisdudesert 1 /* On server side (PHP) */ wikitext text/x-wiki Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them. == How translation works? == When developing your game, all strings must be in English. Strings must be coherent with the English version of the game. Before the release of the game, BGA team will do the French translation of the game. After the release of the game, the BGA players community will translate the game in every language. == What should be translated? == Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ... This does NOT include error messages that are not supposed to happened (unexpected errors). == Focus on translating notifications == Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function. However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side. == On client side (Javascript) == On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate. Examples: <pre> // Get a string in player's language: var translated = _("original english string"); // Get a string in player's language with parameter: var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", { p: 2, d: 4 } ); </pre> Note: what is also possible to do is == On server side (PHP) == On PHP side, you can use 3 different functions to specify that a string must be translated. '''clienttranslate( "my string to translate" ):''' This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side. In general, you use clienttranslate: * On your states.inc.php, for field "description" and "descriptionmyturn". <pre> "description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'), </pre> * On "material.inc.php", when defining texts for game material that must be displayed on client side. <pre> $this->card_types = array( 1 => array( 'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side. </pre> * When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation. <pre> // A game log string with no argument: self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() ); </pre> '''self::_( "my string to translate" ):''' This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player). Most of the time, you don't need to translate strings on server side, except on the following 3 situations: * When throwing an exception because the player did a forbidden move. <pre> // This will display a translatable red message to the player that just do some wrong action: throw new feException( self::_('You must choose 3 cards'), true); // ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated. </pre> * In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file. <pre> $this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II"); </pre> * Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions. <pre> // In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this: throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true ); </pre> * Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user. '''totranslate( "my string to translate" ):''' This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side. You should not use this function, except on the following cases: * Statistics name in stats.inc.php * Option names and option values name in gameoptions.inc.php 9315062d846ea128dd8a5731f15b03d70346e96e 534 533 2013-01-15T17:07:34Z Sourisdudesert 1 /* On server side (PHP) */ wikitext text/x-wiki Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them. == How translation works? == When developing your game, all strings must be in English. Strings must be coherent with the English version of the game. Before the release of the game, BGA team will do the French translation of the game. After the release of the game, the BGA players community will translate the game in every language. == What should be translated? == Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ... This does NOT include error messages that are not supposed to happened (unexpected errors). == Focus on translating notifications == Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function. However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side. == On client side (Javascript) == On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate. Examples: <pre> // Get a string in player's language: var translated = _("original english string"); // Get a string in player's language with parameter: var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", { p: 2, d: 4 } ); </pre> Note: what is also possible to do is == On server side (PHP) == On PHP side, you can use 3 different functions to specify that a string must be translated. '''clienttranslate( "my string to translate" ):''' This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side. In general, you use clienttranslate: * On your states.inc.php, for field "description" and "descriptionmyturn". <pre> "description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'), </pre> * On "material.inc.php", when defining texts for game material that must be displayed on client side. <pre> $this->card_types = array( 1 => array( 'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side. </pre> * When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation. <pre> // A game log string with no argument: self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() ); </pre> Translating arguments is a little bit more complex. It is using the "i18n" special argument as below: <pre> // In the following example, we translate the game log itself, but also the "card_name" argument: self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array( 'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'points' => $points, 'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string. ) ); </pre> '''self::_( "my string to translate" ):''' This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player). Most of the time, you don't need to translate strings on server side, except on the following 3 situations: * When throwing an exception because the player did a forbidden move. <pre> // This will display a translatable red message to the player that just do some wrong action: throw new feException( self::_('You must choose 3 cards'), true); // ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated. </pre> * In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file. <pre> $this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II"); </pre> * Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions. <pre> // In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this: throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true ); </pre> * Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user. '''totranslate( "my string to translate" ):''' This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side. You should not use this function, except on the following cases: * Statistics name in stats.inc.php * Option names and option values name in gameoptions.inc.php b0251a213ab68551932ef7c5129f4d59dce827af Help 0 4 507 427 2013-01-11T16:02:09Z Een 3 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] 401acc1457522cd40f7eeb302f5488ea375cbacb Game statistics: stats.inc.php 0 95 512 2013-01-11T16:11:38Z Sourisdudesert 1 Created page with " (todo)" wikitext text/x-wiki (todo) 144a80e923365406965058d618e72ad9edcf31e0 519 512 2013-01-11T16:52:46Z Sourisdudesert 1 wikitext text/x-wiki (to be completed) => see comments in your stats.inc.php file a01448ec26bcc5d5e1468c200ce2385a6c5e3145 Game interface stylesheet: yourgamename.css 0 96 520 2013-01-11T17:05:10Z Sourisdudesert 1 Created page with "This is the CSS stylesheet of your game User Interface. Styles defined on this file will be applied to the HTML elements you define in your HTML template (yourgame_yourga..." wikitext text/x-wiki This is the CSS stylesheet of your game User Interface. Styles defined on this file will be applied to the HTML elements you define in your HTML template (yourgame_yourgame.tpl), and to HTML elements you create dynamically with Javascript. Usually, you are using CSS to: 1°) define the overall layout of your game (ex: place the board on the top left, place player's hand beside, place the deck on the right, ...). 2°) create your CSS-sprites: All images of your games should be gathered into a small number of image files. Then, using background-image and background-position CSS properties, you create HTML blocks that can display these images correctly. Example: <pre> Example of CSS sprites (a black token and a white token, 20x20px each, embedded in the same "tokens.png" 40x20px image): .white_token { background-image: url('../../img/emptygame/tokens.png'); background-position: 0px 0px; } .black_token { background-image: url('../../img/emptygame/tokens.png'); background-position: -20px 0px; } .token { width: 20px; height: 20px; background-repeat: none; } </pre> 3°) ... anything else: It is really easy to add and remove CSS classes dynamically from your Javascript with dojo.addClass and dojo.removeClass. It is also easy to check if an element has a class (dojo.hasClass) or to get all elements with a specific class (dojo.query). This is why, very often, using CSS classes for the logic of your user interface allow you to do complex thing easily. Note: on the production platform, this file will be compressed and comments will be removed. Consequently, don't hesitate to put as many comments as necessary. e3a85e1f26e247f89f549b3427b62770dd4ba20f How to join BGA developer team? 0 83 521 431 2013-01-13T12:07:41Z Een 3 /* Ok, I registered, what do I get? */ wikitext text/x-wiki Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your player user name on BGA * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf 'terms & conditions' document]. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: 'I agree with the terms & conditions for developers on BGA Studio joined as an attachment'. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, we'll discuss by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum) Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! 93291e486ca904e0dbed17dcadb4a04271acd827 Game interface logic: yourgamename.js 0 88 522 451 2013-01-14T16:02:38Z Sourisdudesert 1 wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface: TODO == Useful methods from the BGA framework == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 2d591248b137f4f336137161c6c0d8e6fadc5784 523 522 2013-01-14T16:22:11Z Sourisdudesert 1 /* Dojo framework */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface: '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Useful methods from the BGA framework == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player f958116cefb92037d99b5803494b0e77dc5933bb 524 523 2013-01-14T16:28:08Z Sourisdudesert 1 /* Dojo framework */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface: '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''dojo.style''' TODO '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Useful methods from the BGA framework == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player dfcc464befa61dd55fbf2d1dbfbbedc4f8e8ad8c 525 524 2013-01-14T16:46:51Z Sourisdudesert 1 /* Dojo framework */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface: '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Useful methods from the BGA framework == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player e4a4a9ede4662eeb6aba9c6aeacf08c55cfd91d0 526 525 2013-01-14T17:21:17Z Sourisdudesert 1 /* Dojo framework */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface: '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. == Useful methods from the BGA framework == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 07e0e96af372326eb1ccde8fd9b13758b8e25c31 527 526 2013-01-14T17:23:33Z Sourisdudesert 1 /* Dojo framework */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface: '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. '''dojo animations''' See "animations" below. '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. == Useful methods from the BGA framework == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player df3c2d0d3f9af0259ea4c3a8c70edf7422cad672 528 527 2013-01-14T17:27:28Z Sourisdudesert 1 wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == == Access and manipulate the DOM == == Animations == == Players input == (dojo.connect/checkAction/ajaxcall/confirmationDialog) == Notifications == == Tooltips == == BGA GUI components == == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface: '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. '''dojo animations''' See "animations" below. '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. == Useful methods from the BGA framework == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 808f170e17bf773369f5fa182d57e47ad36472f3 535 528 2013-01-15T17:28:55Z Sourisdudesert 1 /* Useful methods from the BGA framework */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == == Access and manipulate the DOM == == Animations == == Players input == (dojo.connect/checkAction/ajaxcall/confirmationDialog) == Notifications == == Tooltips == == BGA GUI components == == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface: '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. '''dojo animations''' See "animations" below. '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. == Useful methods from the BGA framework == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 5a821d5a7574d0e44e801b374da78484bf054ee8 536 535 2013-01-15T17:30:17Z Sourisdudesert 1 /* General tips */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Access and manipulate the DOM == == Animations == == Players input == (dojo.connect/checkAction/ajaxcall/confirmationDialog) == Notifications == == Tooltips == == BGA GUI components == == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. Here's the list of the most useful methods you can use for your game interface: '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. '''dojo animations''' See "animations" below. '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. == Useful methods from the BGA framework == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 500ffcf842c54b3d538b5b5bf0b09e97d468de80 537 536 2013-01-15T17:39:45Z Sourisdudesert 1 wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Animations == == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' TODO '''this.ajaxcall()''' TODO Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> == Notifications == == Tooltips == == BGA GUI components == '''dojo animations''' See "animations" below. '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. == Useful methods from the BGA framework == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 5925d7515da319684b74df69c34f3c44b7701ac4 538 537 2013-01-15T17:40:11Z Sourisdudesert 1 /* Useful methods from the BGA framework */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Animations == == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' TODO '''this.ajaxcall()''' TODO Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> == Notifications == == Tooltips == == BGA GUI components == '''dojo animations''' See "animations" below. '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. == Useful methods from the BGA framework == ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 75121e76f663a1539f180b725447d90adeecd4d5 539 538 2013-01-15T17:40:21Z Sourisdudesert 1 /* Animations */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' TODO '''this.ajaxcall()''' TODO Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> == Notifications == == Tooltips == == BGA GUI components == '''dojo animations''' See "animations" below. '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. == Useful methods from the BGA framework == ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 50f6adb55d71b5fce9f62374c9ab7d9d4861f745 540 539 2013-01-15T17:40:39Z Sourisdudesert 1 /* BGA GUI components */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' TODO '''this.ajaxcall()''' TODO Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> == Notifications == == Tooltips == == BGA GUI components == == Useful methods from the BGA framework == ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 90a053e179d91c2b7422976bf185e9f9717fdf62 541 540 2013-01-15T17:41:24Z Sourisdudesert 1 /* Useful methods from the BGA framework */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' TODO '''this.ajaxcall()''' TODO Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> == Notifications == == Tooltips == == BGA GUI components == == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player b8f913e1bc2aa33d972f84996dd998cd11cd3cf2 542 541 2013-01-15T17:41:32Z Sourisdudesert 1 /* Tooltips */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' TODO '''this.ajaxcall()''' TODO Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> == Notifications == == Tooltips == ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips == BGA GUI components == == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player e9c7a0524cff660e9ecc2cec157ee42827a9d76e 543 542 2013-01-15T17:41:53Z Sourisdudesert 1 /* Other useful stuff */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' TODO '''this.ajaxcall()''' TODO Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> == Notifications == == Tooltips == ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips == BGA GUI components == == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 21cd7cce3f7b0eebdab0b1b4bc17374c27817254 544 543 2013-01-15T17:42:27Z Sourisdudesert 1 /* Players input */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: _ current game state & _ interface locking return true if action is authorized return false and display an error message if not (display no message if nomessage parameter is true) '''this.ajaxcall()''' TODO Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> == Notifications == == Tooltips == ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips == BGA GUI components == == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 9c7028944c23584ab2d72a72d9594fd21bb286e0 545 544 2013-01-15T17:44:47Z Sourisdudesert 1 /* BGA GUI components */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: _ current game state & _ interface locking return true if action is authorized return false and display an error message if not (display no message if nomessage parameter is true) '''this.ajaxcall()''' TODO Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> == Notifications == == Tooltips == ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface. [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 25369aba21f0c435dfa537d7ac4a2fc67358583a 546 545 2013-01-15T17:45:07Z Sourisdudesert 1 /* BGA GUI components */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: _ current game state & _ interface locking return true if action is authorized return false and display an error message if not (display no message if nomessage parameter is true) '''this.ajaxcall()''' TODO Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> == Notifications == == Tooltips == ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 8e75a75f76580e2f9cb781117094561f3c640a9a 547 546 2013-01-15T17:45:19Z Sourisdudesert 1 /* Other useful stuff */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: _ current game state & _ interface locking return true if action is authorized return false and display an error message if not (display no message if nomessage parameter is true) '''this.ajaxcall()''' TODO Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> == Notifications == == Tooltips == ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 53fd25d376669bf4a89e2f54ff0832e2129018b5 548 547 2013-01-15T17:45:33Z Sourisdudesert 1 /* Players input */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: _ current game state & _ interface locking return true if action is authorized return false and display an error message if not (display no message if nomessage parameter is true) '''this.ajaxcall()''' TODO Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Notifications == == Tooltips == ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 7118f94dfa528ed0ff07820f66e558f73d350d66 549 548 2013-01-15T17:45:45Z Sourisdudesert 1 /* Other useful stuff */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: _ current game state & _ interface locking return true if action is authorized return false and display an error message if not (display no message if nomessage parameter is true) '''this.ajaxcall()''' TODO Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Notifications == == Tooltips == ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 5b54585df2c6e96126c1a881c0cdf6a6410227b7 Game interface logic: yourgamename.js 0 88 550 549 2013-01-15T17:45:57Z Sourisdudesert 1 /* Access and manipulate the DOM */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: _ current game state & _ interface locking return true if action is authorized return false and display an error message if not (display no message if nomessage parameter is true) '''this.ajaxcall()''' TODO Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Notifications == == Tooltips == ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player d847a4298f2d48659e7abac127332ca299483882 560 550 2013-01-29T20:16:07Z Sourisdudesert 1 /* Tooltips */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: _ current game state & _ interface locking return true if action is authorized return false and display an error message if not (display no message if nomessage parameter is true) '''this.ajaxcall()''' TODO Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Notifications == == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player cca113c65beb3f4b496694319e19911ae4adbf02 561 560 2013-01-29T20:23:45Z Sourisdudesert 1 /* Players input */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Notifications == == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 7c1c1a5b909b7d3a6974119c27e7cb3648bd91d5 571 561 2013-01-29T21:21:55Z Sourisdudesert 1 /* Access and manipulate the DOM */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Notifications == == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 89b39331514986dad84a1f8c6f5d7ad8ad561b3e 572 571 2013-01-29T21:22:21Z Sourisdudesert 1 /* Access and manipulate the DOM */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Notifications == == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 593b196f904b35192fcc41acc623cc34b71e88b9 Referral 0 11 551 90 2013-01-18T13:35:33Z Een 3 /* How does this work? */ wikitext text/x-wiki [[Category:Help]] When new players discover Board Game Arena thanks to you, you become a member of [[Club Board Game Arena]] == How does this work? == Each time a new player creates an account on Board Game Arena from your referrer web address (see below), he becomes one of your '''referees'''. As soon as this referee plays 3 games, you become a member of BGA club. == How to get referees? == To recruit referees, use your personal referrer web address: {sponsorshipurl} New players MUST create an account from this web address to become one of your referees. == How to get many referees? == * [http://boardgamearena.com/#!doc/sponsor?facebook Tell my friends on Facebook] * [http://boardgamearena.com/#!doc/sponsor?twitter Tell my followers on Twitter] * [http://boardgamearena.com/#!doc/sponsor?email Tell my friends by email] * Publish my personal web address in some forum, send it by MSN, ... == How many BGA club membership days can I win? == As soon as your first referee finish his '''third''' game on Board Game Arena, you win a '''1 month''' BGA club membership. ''Note: your account upgrade will be effective within 24 hours.'' As soon as you get '''2 referees''' with at least '''4 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership. As soon as you get '''3 referees''' with at least '''5 games''' logged on Board Game Arena, you win another '''1 month''' BGA club membership. ... and so on: as your referees number grows you can win many free memberships ! == Referees and multiple accounts == It is of course forbidden to create fake referee accounts to win free memberships. 9eb06a83374493fecff6c484c9c14cc24b2bea66 Studio FAQ 0 53 552 421 2013-01-19T13:24:35Z Een 3 wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == I can't edit the file, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. b45616fb440438f17118e394471ad3458d8347a5 553 552 2013-01-19T13:24:53Z Een 3 /* I can't edit the file, it looks like they are readonly. What's happening? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == I can't edit the files for my game, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. bf2990a44d913df03be605bae6635a5712829a0d 554 553 2013-01-19T13:25:09Z Een 3 /* I can't edit the files for my game, it looks like they are readonly. What's happening? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == I can't edit the files in my game directory, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. 28e961be7320545802f150b6304b957d62ffe350 573 554 2013-01-29T21:23:27Z Sourisdudesert 1 /* How can I provide translation in my language? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == I can't edit the files in my game directory, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. Check [[Translations]] to see how to make your game translatable. == Is there a special way to declare the strings that must be translated? == Yes. This declaration is made through transparent functions, that depend on the context. In javascript files, you should use _( 'My string to translate' ). In php files, you should use self::_( 'My string to translate' ) when the string can be translated on the server side (ex: title included in the game layout) and clienttranslate( 'My string to translate' ) when the string must be translated on the client side (ex: message for the game log). == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. 228c35f8d6f017ce425e4137252e104afe9127d0 574 573 2013-01-29T21:23:43Z Sourisdudesert 1 /* Is there a special way to declare the strings that must be translated? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == I can't edit the files in my game directory, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == It's pretty annoying to log in with multiple users to start a game. Is there some easier way? == You can use the 'Express start' function. It will automatically make the specified number of players join the game (using the first of your ten player accounts available) and start the game. During the game, there is a red arrow on the right of each player name, that you can use to open a tab from this player's perspective. You can also end the game in two clicks by clicking the 'End game' button then selecting 'Express game stop' in the popup. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. Check [[Translations]] to see how to make your game translatable. == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. e36087c923ca5e0d25409eec810218f72e8c8f9f 576 574 2013-01-29T21:29:11Z Sourisdudesert 1 /* It's pretty annoying to log in with multiple users to start a game. Is there some easier way? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == I can't edit the files in my game directory, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. Check [[Translations]] to see how to make your game translatable. == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Is there a quick way to access the database for my current table? == Yes! While playing a game on studio, you have a "Go to game database" link at the bottom of your game. This link will bring you directly to the database for the current table. == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. 71a874d035ff4e8a5dc743da16fbb62b6344e8eb 580 576 2013-01-29T21:44:02Z Sourisdudesert 1 /* Is there a quick way to access the database for my current table? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the WinSCP client. == I can't edit the files in my game directory, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. Check [[Translations]] to see how to make your game translatable. == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. c0989601e76d0ccf881330ba3f51785befb55fd5 581 580 2013-01-29T21:44:54Z Sourisdudesert 1 /* What should I use to access the files through SFTP? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the [http://winscp.net/ WinSCP client]. == I can't edit the files in my game directory, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. Check [[Translations]] to see how to make your game translatable. == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. 0c5d2fe1d5482e222473398fe6bd8f5bcdb945b0 582 581 2013-01-29T21:52:06Z Sourisdudesert 1 /* What is the best way to debug? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the [http://winscp.net/ WinSCP client]. == I can't edit the files in my game directory, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. Check [[Translations]] to see how to make your game translatable. == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. d23029c5aaa00274a69aa2bd89e4b30be505699e Stock 0 97 555 2013-01-21T10:42:32Z Sourisdudesert 1 Created page with " "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Sto..." wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. aaa3491d40e9f58eb0c33a075306bbfaf932c973 556 555 2013-01-21T10:42:51Z Sourisdudesert 1 wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. (TODO) 259bdd5d57b95bb36ea7250c0d64f61c85daa016 557 556 2013-01-23T06:45:58Z Sourisdudesert 1 /* Complete stock component reference */ wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: _ type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. _ weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted). _ image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_themeurl+'img/your_game_name/yourimage.png' </pre> _ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. 596e2d334136943a584826bf495ae8cf793d5510 559 557 2013-01-26T04:58:23Z Pikiou 1872 /* Complete stock component reference */ wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: _ type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. _ weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted). _ image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_themeurl+'img/your_game_name/yourimage.png' </pre> _ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. d9a22a4260d98df2ad1fd5eefe00d825b91c94a7 Gamehelpintheyearofthedragon 0 51 558 227 2013-01-25T07:25:06Z Chefneil 2211 /* End-of-game Scoring */ wikitext text/x-wiki === End-of-round Scoring === * 1 point for each palace. * 1 point For each court lady. * 1 point For each privilege. (Small privilege = 1 point; Large privilege = 2 points) === End-of-game Scoring === * 2 points for each person tile. * For each monk: score [number of Buddhas] x [number of floors] points. * Each player sells back to the supply all of his rice and fireworks tiles for 2 yuan each.Afterward, each player earns 1 victory point for every 3 yuan he possesses. d14091f98a1adfed010f5ef619850821e1c47d1b Main game logic: yourgamename.game.php 0 86 562 518 2013-01-29T20:30:13Z Sourisdudesert 1 /* Translations */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. 4d7d4744233cd8afd5bd1c1aa6db76ab3570a8d1 563 562 2013-01-29T20:38:07Z Sourisdudesert 1 /* Manage player scores and Tie breaker */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the following methods: ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this: <pre> $this->tie_breaker_description = self::_("Describe here your tie breaker formula"); </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. 5fbea32b7752c400ce2e16ca6200144df516f94d 586 563 2013-01-29T22:10:38Z Sourisdudesert 1 /* Accessing database */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. IMPORTANT: BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this: <pre> $this->tie_breaker_description = self::_("Describe here your tie breaker formula"); </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. 51b1fdd1370f93c3b2c675b52245872c70fa5754 587 586 2013-01-29T22:11:00Z Sourisdudesert 1 /* Accessing database */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this: <pre> $this->tie_breaker_description = self::_("Describe here your tie breaker formula"); </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. 6502226df993ec63c7c972714147ec92d7471ffe 588 587 2013-01-29T22:11:07Z Sourisdudesert 1 /* Accessing database */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notification, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this: <pre> $this->tie_breaker_description = self::_("Describe here your tie breaker formula"); </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. 6282c3822e4e213200925c1cc8200f6af6ed3443 589 588 2013-01-29T22:12:43Z Sourisdudesert 1 /* Notify players */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this: <pre> $this->tie_breaker_description = self::_("Describe here your tie breaker formula"); </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. f2ac5c9d3fd78ef14e0c1ce46b4d58df770dcba0 590 589 2013-01-29T22:14:15Z Sourisdudesert 1 /* Managing errors and exceptions */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this: <pre> $this->tie_breaker_description = self::_("Describe here your tie breaker formula"); </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. 1185bc779ecad94a1a233b0387229b9f919a6527 Game layout: view and template: yourgamename.view.php and yourgamename yourgamename.tpl 0 98 564 2013-01-29T20:53:10Z Sourisdudesert 1 Created page with "These 2 files work together to provide the HTML layout of your game. Using these 2 files, you specify what HTML is rendered in your game client interface. In <yourgame.tpl>,..." wikitext text/x-wiki These 2 files work together to provide the HTML layout of your game. Using these 2 files, you specify what HTML is rendered in your game client interface. In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser. Example: extract of "reversi_reversi.tpl": <pre> <div id="myhand_wrap" class="whiteblock"> <h3>{MY_HAND}</h3> <div id="myhand"> </div> </div> </pre> == phplib template system == BGA is using the phplib template system, used for example in PHPbb forums. More details about how to use phplib template system here: http://www.phpbuilder.com/columns/david20000512.php3 == Variables == In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value. In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}". To give a value to this variable in your view.php: Examples: <pre> // Display a translated version of "My hand" at the place of the variable in the template $this->tpl['MY_HAND'] = self::_("My hand"); // Display some raw HTML material at the place of the variable $this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" ); </pre> ab1fa2414a3eb4c232aea1ee4034fcacd33db6a6 565 564 2013-01-29T20:59:20Z Sourisdudesert 1 wikitext text/x-wiki These 2 files work together to provide the HTML layout of your game. Using these 2 files, you specify what HTML is rendered in your game client interface. In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser. Example: extract of "reversi_reversi.tpl": <pre> <div id="myhand_wrap" class="whiteblock"> <h3>{MY_HAND}</h3> <div id="myhand"> </div> </div> </pre> == WARNING == Your view and your template are supposed to generate only the BASE layout of the game You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :) Example of things to generate in your view: * The overall layout of your game interface (what is displayed where). * The board and fixed elements on the board (ex: places for cards, squares, ...). Example of things that shouldn't be generate by your view: * Game elements that come and go from the game area. * Game elements that are moving from one place to another. == phplib template system == BGA is using the phplib template system, used for example in PHPbb forums. More details about how to use phplib template system here: http://www.phpbuilder.com/columns/david20000512.php3 == Variables == In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value. In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}". To give a value to this variable in your view.php: Examples: <pre> // Display a translated version of "My hand" at the place of the variable in the template $this->tpl['MY_HAND'] = self::_("My hand"); // Display some raw HTML material at the place of the variable $this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" ); </pre> == Blocks == 1cbe6c9723a2d6bd6ac9ad8d975396e73c9c7645 566 565 2013-01-29T21:03:29Z Sourisdudesert 1 /* Blocks */ wikitext text/x-wiki These 2 files work together to provide the HTML layout of your game. Using these 2 files, you specify what HTML is rendered in your game client interface. In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser. Example: extract of "reversi_reversi.tpl": <pre> <div id="myhand_wrap" class="whiteblock"> <h3>{MY_HAND}</h3> <div id="myhand"> </div> </div> </pre> == WARNING == Your view and your template are supposed to generate only the BASE layout of the game You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :) Example of things to generate in your view: * The overall layout of your game interface (what is displayed where). * The board and fixed elements on the board (ex: places for cards, squares, ...). Example of things that shouldn't be generate by your view: * Game elements that come and go from the game area. * Game elements that are moving from one place to another. == phplib template system == BGA is using the phplib template system, used for example in PHPbb forums. More details about how to use phplib template system here: http://www.phpbuilder.com/columns/david20000512.php3 == Variables == In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value. In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}". To give a value to this variable in your view.php: Examples: <pre> // Display a translated version of "My hand" at the place of the variable in the template $this->tpl['MY_HAND'] = self::_("My hand"); // Display some raw HTML material at the place of the variable $this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" ); </pre> == Blocks == Using "blocks", you can repeat a piece of HTML from your template several time. You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares: <pre> (in reversi_reversi.tpl) <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> <div id="discs"> </div> </div> (in reversi.view.php) $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> be61b0d8430efd6be334f471987d1957b13d11e1 567 566 2013-01-29T21:03:49Z Sourisdudesert 1 wikitext text/x-wiki These 2 files work together to provide the HTML layout of your game. Using these 2 files, you specify what HTML is rendered in your game client interface. In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser. Example: extract of "hearts_hearts.tpl": <pre> <div id="myhand_wrap" class="whiteblock"> <h3>{MY_HAND}</h3> <div id="myhand"> </div> </div> </pre> == WARNING == Your view and your template are supposed to generate only the BASE layout of the game You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :) Example of things to generate in your view: * The overall layout of your game interface (what is displayed where). * The board and fixed elements on the board (ex: places for cards, squares, ...). Example of things that shouldn't be generate by your view: * Game elements that come and go from the game area. * Game elements that are moving from one place to another. == phplib template system == BGA is using the phplib template system, used for example in PHPbb forums. More details about how to use phplib template system here: http://www.phpbuilder.com/columns/david20000512.php3 == Variables == In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value. In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}". To give a value to this variable in your view.php: Examples: <pre> // Display a translated version of "My hand" at the place of the variable in the template $this->tpl['MY_HAND'] = self::_("My hand"); // Display some raw HTML material at the place of the variable $this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" ); </pre> == Blocks == Using "blocks", you can repeat a piece of HTML from your template several time. You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares: <pre> (in reversi_reversi.tpl) <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> <div id="discs"> </div> </div> (in reversi.view.php) $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> b72e8c036aae4063866997eef8e29091924aa682 568 567 2013-01-29T21:06:50Z Sourisdudesert 1 /* Blocks */ wikitext text/x-wiki These 2 files work together to provide the HTML layout of your game. Using these 2 files, you specify what HTML is rendered in your game client interface. In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser. Example: extract of "hearts_hearts.tpl": <pre> <div id="myhand_wrap" class="whiteblock"> <h3>{MY_HAND}</h3> <div id="myhand"> </div> </div> </pre> == WARNING == Your view and your template are supposed to generate only the BASE layout of the game You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :) Example of things to generate in your view: * The overall layout of your game interface (what is displayed where). * The board and fixed elements on the board (ex: places for cards, squares, ...). Example of things that shouldn't be generate by your view: * Game elements that come and go from the game area. * Game elements that are moving from one place to another. == phplib template system == BGA is using the phplib template system, used for example in PHPbb forums. More details about how to use phplib template system here: http://www.phpbuilder.com/columns/david20000512.php3 == Variables == In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value. In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}". To give a value to this variable in your view.php: Examples: <pre> // Display a translated version of "My hand" at the place of the variable in the template $this->tpl['MY_HAND'] = self::_("My hand"); // Display some raw HTML material at the place of the variable $this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" ); </pre> == Blocks == Using "blocks", you can repeat a piece of HTML from your template several time. You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares: <pre> (in reversi_reversi.tpl) <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> <div id="discs"> </div> </div> (in reversi.view.php) $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Explanations: * You specify a block in your template file, using "BEGIN" and "END" keywords. In the example above, we are creating a block named "square". * In your view, you declare your block using "begin_block" method. * Then, you can insert as many block as you want to, using "insert_block" method. The insert_block method takes 2 parameters: * the name of the block to insert. * an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP). 01e70246e836e8ea7fdc7274434f54f6b8027375 569 568 2013-01-29T21:15:22Z Sourisdudesert 1 /* Blocks */ wikitext text/x-wiki These 2 files work together to provide the HTML layout of your game. Using these 2 files, you specify what HTML is rendered in your game client interface. In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser. Example: extract of "hearts_hearts.tpl": <pre> <div id="myhand_wrap" class="whiteblock"> <h3>{MY_HAND}</h3> <div id="myhand"> </div> </div> </pre> == WARNING == Your view and your template are supposed to generate only the BASE layout of the game You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :) Example of things to generate in your view: * The overall layout of your game interface (what is displayed where). * The board and fixed elements on the board (ex: places for cards, squares, ...). Example of things that shouldn't be generate by your view: * Game elements that come and go from the game area. * Game elements that are moving from one place to another. == phplib template system == BGA is using the phplib template system, used for example in PHPbb forums. More details about how to use phplib template system here: http://www.phpbuilder.com/columns/david20000512.php3 == Variables == In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value. In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}". To give a value to this variable in your view.php: Examples: <pre> // Display a translated version of "My hand" at the place of the variable in the template $this->tpl['MY_HAND'] = self::_("My hand"); // Display some raw HTML material at the place of the variable $this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" ); </pre> == Blocks == Using "blocks", you can repeat a piece of HTML from your template several time. You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares: <pre> (in reversi_reversi.tpl) <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> <div id="discs"> </div> </div> (in reversi.view.php) $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Explanations: * You specify a block in your template file, using "BEGIN" and "END" keywords. In the example above, we are creating a block named "square". * In your view, you declare your block using "begin_block" method. * Then, you can insert as many block as you want to, using "insert_block" method. The insert_block method takes 2 parameters: * the name of the block to insert. * an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP). == Nested blocks == You can use nested blocks. In the example below, we are going to add a mini-board for each player of the game, with 4 card places on each of it: <pre> (In template file) <!-- BEGIN player --> <div class="miniboard" id="miniboard_{PLAYER_ID}"> <div class="card_places"> <!-- BEGIN card_place --> <div id="card_place_{PLAYER_ID}_{PLACE_ID}"> </div> <!-- END card_place --> </div> </div> <!-- END player --> (In view file) $this->page->begin_block( "mygame_mygame.tpl", "card_place" ); // Nested block must be declared first $this->page->begin_block( "mygame_mygame.tpl", "player" ); foreach( $players as $player_id => $player ) { // Important: nested block must be reset here, otherwise the second player miniboard will // have 8 card_place, the third will have 12 card_place, and so one... $this->page->reset_subblocks( 'card_place' ); for( $i=1; $i<=4; $i++ ) { $this->page->insert_block( "card_place", array( 'PLAYER_ID' => $player_id, 'PLACE_ID' => $i ); } $this->page->insert_block( 'player', array( 'PLAYER_ID' => $player_id ); } </pre> b6cd67e2292dd8601b8c6a6f00338aa000a8901b 570 569 2013-01-29T21:19:50Z Sourisdudesert 1 wikitext text/x-wiki These 2 files work together to provide the HTML layout of your game. Using these 2 files, you specify what HTML is rendered in your game client interface. In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser. Example: extract of "hearts_hearts.tpl": <pre> <div id="myhand_wrap" class="whiteblock"> <h3>{MY_HAND}</h3> <div id="myhand"> </div> </div> </pre> == WARNING == Your view and your template are supposed to generate only the BASE layout of the game You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :) Example of things to generate in your view: * The overall layout of your game interface (what is displayed where). * The board and fixed elements on the board (ex: places for cards, squares, ...). Example of things that shouldn't be generate by your view: * Game elements that come and go from the game area. * Game elements that are moving from one place to another. == phplib template system == BGA is using the phplib template system, used for example in PHPbb forums. More details about how to use phplib template system here: http://www.phpbuilder.com/columns/david20000512.php3 == Variables == In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value. In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}". To give a value to this variable in your view.php: Examples: <pre> // Display a translated version of "My hand" at the place of the variable in the template $this->tpl['MY_HAND'] = self::_("My hand"); // Display some raw HTML material at the place of the variable $this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" ); </pre> == Blocks == Using "blocks", you can repeat a piece of HTML from your template several time. You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares: <pre> (in reversi_reversi.tpl) <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> <div id="discs"> </div> </div> (in reversi.view.php) $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Explanations: * You specify a block in your template file, using "BEGIN" and "END" keywords. In the example above, we are creating a block named "square". * In your view, you declare your block using "begin_block" method. * Then, you can insert as many block as you want to, using "insert_block" method. The insert_block method takes 2 parameters: * the name of the block to insert. * an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP). == Nested blocks == You can use nested blocks. In the example below, we are going to add a mini-board for each player of the game, with 4 card places on each of it: <pre> (In template file) <!-- BEGIN player --> <div class="miniboard" id="miniboard_{PLAYER_ID}"> <div class="card_places"> <!-- BEGIN card_place --> <div id="card_place_{PLAYER_ID}_{PLACE_ID}"> </div> <!-- END card_place --> </div> </div> <!-- END player --> (In view file) $this->page->begin_block( "mygame_mygame.tpl", "card_place" ); // Nested block must be declared first $this->page->begin_block( "mygame_mygame.tpl", "player" ); foreach( $players as $player_id => $player ) { // Important: nested block must be reset here, otherwise the second player miniboard will // have 8 card_place, the third will have 12 card_place, and so one... $this->page->reset_subblocks( 'card_place' ); for( $i=1; $i<=4; $i++ ) { $this->page->insert_block( "card_place", array( 'PLAYER_ID' => $player_id, 'PLACE_ID' => $i ); } $this->page->insert_block( 'player', array( 'PLAYER_ID' => $player_id ); } </pre> == Javascript templates == For game elements that come and go from the game area, we suggest you to define a Javascript template. A Javascript template is defined in your template file like this: (Reversi Token from Reversi example): <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: a section for javascript templates is already available at the end of your template skeleton file. Then, you can use this javascript template to insert this piece of HTML in your game interface, like this: <pre> dojo.place( this.format_block( 'jstpl_disc', { xy: x+''+y, color: color } ) , 'discs' ); </pre> 9806b9dfa29915aec140a1017843edaa96b9cd79 Studio 0 49 575 529 2013-01-29T21:25:00Z Sourisdudesert 1 /* BGA Studio user guide */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Tools and tips of BGA Studio]] [[Practical debugging]] [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 71afcb42b7cf6027b4c429ccf53881bf70a0dfc5 Tools and tips of BGA Studio 0 99 577 2013-01-29T21:31:32Z Sourisdudesert 1 Created page with "== Starting a game in one click == To start a game: * Create a new table with your game. * If you want to play a game with 3 players, specify that you want a maximum of 3 pla..." wikitext text/x-wiki == Starting a game in one click == To start a game: * Create a new table with your game. * If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table. * Click on "Express Start". == Stopping a game in one click == * Click on the "quit" icon on the top right of the screen. * Click on "Express Stop". == Switching between users == when running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective. == Access to game database == Immediately at the bottom of the game area, the "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game. == Input/Output debugging section == 4b27048eb61349acf7cff6a912e8cd7df429beee 578 577 2013-01-29T21:39:56Z Sourisdudesert 1 /* Input/Output debugging section */ wikitext text/x-wiki == Starting a game in one click == To start a game: * Create a new table with your game. * If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table. * Click on "Express Start". == Stopping a game in one click == * Click on the "quit" icon on the top right of the screen. * Click on "Express Stop". == Switching between users == when running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective. == Access to game database == Immediately at the bottom of the game area, the "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game. == Save & restore state == Using links of this section, you can save the complete current (database) state of your game, then restore it later. This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine. We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations. Limits: * the "restore" function does not work anymore when the game is over. * a saved situation from a given table cannot be restored in another table. * when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually. == Input/Output debugging section == This section shows you: * The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">" * The notifications received by your game interface. Notifications (inputs) begins with "<". Note: if you click on some notification title, you can resend it immediately to the user interface. 607228e76ddee8545782d4adb3003f0e4507cbc9 579 578 2013-01-29T21:42:54Z Sourisdudesert 1 wikitext text/x-wiki == Starting a game in one click == To start a game: * Create a new table with your game. * If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table. * Click on "Express Start". == Stopping a game in one click == * Click on the "quit" icon on the top right of the screen. * Click on "Express Stop". == Switching between users == when running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective. == Access to game database == Immediately at the bottom of the game area, the "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game. == Save & restore state == Using links of this section, you can save the complete current (database) state of your game, then restore it later. This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine. We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations. Limits: * the "restore" function does not work anymore when the game is over. * a saved situation from a given table cannot be restored in another table. * when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually. == Input/Output debugging section == This section shows you: * The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">" * The notifications received by your game interface. Notifications (inputs) begins with "<". Note: if you click on some notification title, you can resend it immediately to the user interface. == Run from the chat == On BGA Studio, you can directly run a PHP method from the chat. For example, if on your PHP you have this method: <pre> function giveMoneyToPlayer($player_id, $amount) { // Do some stuff } </pre> You can call this method directly from the chat like this: "giveMoneyToCurrentPlayer(2564,2)". 5830ee3dfd380fce44ae7cbc5223a65eb4e15b54 Practical debugging 0 100 583 2013-01-29T21:53:08Z Sourisdudesert 1 Created page with " This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Debu..." wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the Studio backoffice. == Debugging my PHP game logic (or my view) == Debugging PHP is most of the time easy == Debugging my HTML/CSS layout == == Debugging my Javascript game interface logic == == Some frequent errors == == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. aa44fcaeaecdd7c548e30cbeacca25903f08191c 584 583 2013-01-29T21:54:35Z Sourisdudesert 1 /* Debugging my game when it cannot start */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Debugging PHP is most of the time easy == Debugging my HTML/CSS layout == == Debugging my Javascript game interface logic == == Some frequent errors == == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. 8d4dc06fe5c513252e4a5c75711404b51879ba28 585 584 2013-01-29T22:04:44Z Sourisdudesert 1 wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a "die('ok');" PHP statement right after the PHP I am developing/debugging. This way, the PHP request will stop immediately, nothing will be commited to the database, and the game initial situation will remains. == Debugging my HTML/CSS layout == == Debugging my Javascript game interface logic == == Some frequent errors == == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. d8fb000e12a9e4fd6921ed6bf0c2012cc574c113 591 585 2013-01-29T22:18:09Z Sourisdudesert 1 /* Debugging my PHP game logic (or my view) */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. == Debugging my HTML/CSS layout == == Debugging my Javascript game interface logic == == Some frequent errors == == What is the best way to debug? == On the server side (PHP), you can use one of these: * die(var_dump( $variable_to_inspect ); * throw new BgaUserException(var_dump( $variable_to_inspect ); On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. In general for debugging, think of using the 'Save & restore state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. c603f203a8e5dfd46b7ecdaa18e21ff21f0dd7ec 592 591 2013-01-29T22:29:50Z Sourisdudesert 1 wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == === Browsers === To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tooltip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> == Debugging my HTML/CSS layout == == Debugging my Javascript game interface logic == == Some frequent errors == == What is the best way to debug? == On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. 0cafffec180d2a8f54155d7119ff55c2acbfe733 593 592 2013-01-29T22:30:46Z Sourisdudesert 1 /* Tools */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tooltip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> == Debugging my HTML/CSS layout == == Debugging my Javascript game interface logic == == Some frequent errors == == What is the best way to debug? == On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. c223b0d05f92488930d83663bc3e2977ceac439f 594 593 2013-01-29T22:30:57Z Sourisdudesert 1 /* General tooltip for debugging */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> == Debugging my HTML/CSS layout == == Debugging my Javascript game interface logic == == Some frequent errors == == What is the best way to debug? == On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. f446e2bbceb1f7a0c2685da8aa1eccacf627d645 595 594 2013-01-29T22:39:27Z Sourisdudesert 1 /* Debugging my HTML/CSS layout */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> == Debugging my HTML/CSS layout == Situation examples: * why my game element doesn't show up in the interface? * why my CSS property hasn't been applied to this element? * why this game element is displayed at this position? A first useful tip when an element does not show up in the interface is to give it a red background: <pre> #my_element { ... some CSS definitions ... background-color: red; } </pre> This way, you know if the element is not visible because of some of its CSS property or because of anything else. Using Chrome "Elements" tab (thre first one), you can: * See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code. * Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles. * You can even modify directly some CSS property and see if how it looks immediately on the game interface. == Debugging my Javascript game interface logic == == Some frequent errors == == What is the best way to debug? == On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. 09a63b6229f62026d949b7ede710534f5e0b36cc 596 595 2013-01-29T22:41:41Z Sourisdudesert 1 /* Debugging my HTML/CSS layout */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> == Debugging my HTML/CSS layout == Situation examples: * why my game element doesn't show up in the interface? * why my CSS property hasn't been applied to this element? * why this game element is displayed at this position? A first useful tip when an element does not show up in the interface is to give it a red background: <pre> #my_element { ... some CSS definitions ... background-color: red; } </pre> This way, you know if the element is not visible because of some of its CSS property or because of anything else. Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property. Using Chrome "Elements" tab (thre first one), you can: * See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code. * Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles. * You can even modify directly some CSS property and see if how it looks immediately on the game interface. == Debugging my Javascript game interface logic == == Some frequent errors == == What is the best way to debug? == On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: * console.log( variable_to_inspect ); will give you the object structure of the variable in the Firebug console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. * alert( variable_to_inspect ); will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. 4a98b70a461dfb2203e4ef49ab559c0fd396ff8f 597 596 2013-01-29T22:41:56Z Sourisdudesert 1 /* What is the best way to debug? */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> == Debugging my HTML/CSS layout == Situation examples: * why my game element doesn't show up in the interface? * why my CSS property hasn't been applied to this element? * why this game element is displayed at this position? A first useful tip when an element does not show up in the interface is to give it a red background: <pre> #my_element { ... some CSS definitions ... background-color: red; } </pre> This way, you know if the element is not visible because of some of its CSS property or because of anything else. Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property. Using Chrome "Elements" tab (thre first one), you can: * See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code. * Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles. * You can even modify directly some CSS property and see if how it looks immediately on the game interface. == Debugging my Javascript game interface logic == == Some frequent errors == == What is the best way to debug? == On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. 7acea4428a85c6fe896dc1ade348a17d3a5e9108 598 597 2013-01-29T22:48:50Z Sourisdudesert 1 /* Debugging my Javascript game interface logic */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> == Debugging my HTML/CSS layout == Situation examples: * why my game element doesn't show up in the interface? * why my CSS property hasn't been applied to this element? * why this game element is displayed at this position? A first useful tip when an element does not show up in the interface is to give it a red background: <pre> #my_element { ... some CSS definitions ... background-color: red; } </pre> This way, you know if the element is not visible because of some of its CSS property or because of anything else. Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property. Using Chrome "Elements" tab (thre first one), you can: * See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code. * Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles. * You can even modify directly some CSS property and see if how it looks immediately on the game interface. == Debugging my Javascript game interface logic == Compare to PHP debugging, Javascript debugging can sometimes be painful. Here's are some tips to make your life easier while developing and debugging Javascript: === Do complex things on PHP side === PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first. The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property. Note: check Reversi example for this. === Add traces in your code === You can use the following: '''console.log( variable_to_inspect )''' It will give you the object structure of the variable in the Javascript console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. '''alert( variable_to_inspect )''' It will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. == Some frequent errors == == What is the best way to debug? == On the client side (Javascript), we recommand installing Firebug for Firefox (or using the 'Developer tools' with Chrome that have about the same functionalities), then: === Some frequent errors === ; The following error occurs when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." : Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. 06380bd3a0144fcea81636911402c0ed7e3daeba 599 598 2013-01-29T22:49:08Z Sourisdudesert 1 /* What is the best way to debug? */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> == Debugging my HTML/CSS layout == Situation examples: * why my game element doesn't show up in the interface? * why my CSS property hasn't been applied to this element? * why this game element is displayed at this position? A first useful tip when an element does not show up in the interface is to give it a red background: <pre> #my_element { ... some CSS definitions ... background-color: red; } </pre> This way, you know if the element is not visible because of some of its CSS property or because of anything else. Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property. Using Chrome "Elements" tab (thre first one), you can: * See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code. * Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles. * You can even modify directly some CSS property and see if how it looks immediately on the game interface. == Debugging my Javascript game interface logic == Compare to PHP debugging, Javascript debugging can sometimes be painful. Here's are some tips to make your life easier while developing and debugging Javascript: === Do complex things on PHP side === PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first. The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property. Note: check Reversi example for this. === Add traces in your code === You can use the following: '''console.log( variable_to_inspect )''' It will give you the object structure of the variable in the Javascript console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. '''alert( variable_to_inspect )''' It will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. == Some frequent errors == b7e2f0def9efdc1c661b1f8a9e18e95986cf3546 Practical debugging 0 100 600 599 2013-01-29T22:49:46Z Sourisdudesert 1 /* Some frequent errors */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> == Debugging my HTML/CSS layout == Situation examples: * why my game element doesn't show up in the interface? * why my CSS property hasn't been applied to this element? * why this game element is displayed at this position? A first useful tip when an element does not show up in the interface is to give it a red background: <pre> #my_element { ... some CSS definitions ... background-color: red; } </pre> This way, you know if the element is not visible because of some of its CSS property or because of anything else. Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property. Using Chrome "Elements" tab (thre first one), you can: * See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code. * Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles. * You can even modify directly some CSS property and see if how it looks immediately on the game interface. == Debugging my Javascript game interface logic == Compare to PHP debugging, Javascript debugging can sometimes be painful. Here's are some tips to make your life easier while developing and debugging Javascript: === Do complex things on PHP side === PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first. The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property. Note: check Reversi example for this. === Add traces in your code === You can use the following: '''console.log( variable_to_inspect )''' It will give you the object structure of the variable in the Javascript console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. '''alert( variable_to_inspect )''' It will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. == Some frequent errors == === when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." === Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. a275e649f9e2640946cd8398d7ec6b216a0bc8c7 630 600 2013-01-30T16:17:01Z Sourisdudesert 1 /* Some frequent errors */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> == Debugging my HTML/CSS layout == Situation examples: * why my game element doesn't show up in the interface? * why my CSS property hasn't been applied to this element? * why this game element is displayed at this position? A first useful tip when an element does not show up in the interface is to give it a red background: <pre> #my_element { ... some CSS definitions ... background-color: red; } </pre> This way, you know if the element is not visible because of some of its CSS property or because of anything else. Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property. Using Chrome "Elements" tab (thre first one), you can: * See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code. * Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles. * You can even modify directly some CSS property and see if how it looks immediately on the game interface. == Debugging my Javascript game interface logic == Compare to PHP debugging, Javascript debugging can sometimes be painful. Here's are some tips to make your life easier while developing and debugging Javascript: === Do complex things on PHP side === PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first. The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property. Note: check Reversi example for this. === Add traces in your code === You can use the following: '''console.log( variable_to_inspect )''' It will give you the object structure of the variable in the Javascript console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. '''alert( variable_to_inspect )''' It will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. == Some frequent errors == === when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." === Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. === when refreshing the web page, the interface remains on "Application loading..." === In this case, you probably have a syntax error in your Javascript code, and the interface refuses to load. To find this error, check if there is an error message in the Javascript console (F12). If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition. 8a99f335a3ab6c99af2563f71f88bdc43ea419d6 631 630 2013-01-30T16:31:34Z Sourisdudesert 1 /* Some frequent errors */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> == Debugging my HTML/CSS layout == Situation examples: * why my game element doesn't show up in the interface? * why my CSS property hasn't been applied to this element? * why this game element is displayed at this position? A first useful tip when an element does not show up in the interface is to give it a red background: <pre> #my_element { ... some CSS definitions ... background-color: red; } </pre> This way, you know if the element is not visible because of some of its CSS property or because of anything else. Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property. Using Chrome "Elements" tab (thre first one), you can: * See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code. * Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles. * You can even modify directly some CSS property and see if how it looks immediately on the game interface. == Debugging my Javascript game interface logic == Compare to PHP debugging, Javascript debugging can sometimes be painful. Here's are some tips to make your life easier while developing and debugging Javascript: === Do complex things on PHP side === PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first. The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property. Note: check Reversi example for this. === Add traces in your code === You can use the following: '''console.log( variable_to_inspect )''' It will give you the object structure of the variable in the Javascript console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. '''alert( variable_to_inspect )''' It will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. == Some frequent errors == === when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." === Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. === when refreshing the web page, the interface remains on "Application loading..." === In this case, you probably have a syntax error in your Javascript code, and the interface refuses to load. To find this error, check if there is an error message in the Javascript console (F12). If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition. === When I do a move, I got "Move recorded, waiting for update ..." forever === "Move recorded" means that your ajaxcall request has been sent to the server and returned normally. "Waiting for update" means that your client interface is waiting for some notifications from the server that correspond to the move we just did. If this message stays forever, it is probably that your PHP code does not send any notification when the move happens, which is abnormal. To fix this: add a notifyAllPlayers or a notifyPlayer call in your PHP code. === Some player action is triggered randomly when I click somewhere on the game area === You probably used "dojo.connect" on a null object. In this case, dojo.connect associate the event (ex: "onclick") to the whole game area. Most of the time it happens in this situation, when my_object element does not exists: <pre> dojo.connect( $("my_object"), "onclick", this, function() { ... } </pre> To determine if this is the case, place "alert( $("my_object") )" before the dojo.connect to check if the object exists or not. === Javascript does not know how to sum two numbers === Be careful when you manipulate integers returned by notifications: most of the time, Javascript considers they are Strings and not Integers. As a result: <pre> var i=1; i += notif.args.increment; // With notif.args.increment='1' alert( i ); // i=11 instead of 2 !! Javascript concatenate 2 strings ! </pre> To solve this, to hesitate to use the "toint" function: <pre> var i=1; i += toint( notif.args.increment ); // With notif.args.increment='1' alert( i ); // i=2 :) </pre> 33d94ad6544cac38815e06aab6deb73b0cd2d016 632 631 2013-01-30T16:35:03Z Sourisdudesert 1 /* Javascript does not know how to sum two numbers */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> == Debugging my HTML/CSS layout == Situation examples: * why my game element doesn't show up in the interface? * why my CSS property hasn't been applied to this element? * why this game element is displayed at this position? A first useful tip when an element does not show up in the interface is to give it a red background: <pre> #my_element { ... some CSS definitions ... background-color: red; } </pre> This way, you know if the element is not visible because of some of its CSS property or because of anything else. Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property. Using Chrome "Elements" tab (thre first one), you can: * See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code. * Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles. * You can even modify directly some CSS property and see if how it looks immediately on the game interface. == Debugging my Javascript game interface logic == Compare to PHP debugging, Javascript debugging can sometimes be painful. Here's are some tips to make your life easier while developing and debugging Javascript: === Do complex things on PHP side === PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first. The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property. Note: check Reversi example for this. === Add traces in your code === You can use the following: '''console.log( variable_to_inspect )''' It will give you the object structure of the variable in the Javascript console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. '''alert( variable_to_inspect )''' It will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. == Some frequent errors == === when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." === Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. === when refreshing the web page, the interface remains on "Application loading..." === In this case, you probably have a syntax error in your Javascript code, and the interface refuses to load. To find this error, check if there is an error message in the Javascript console (F12). If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition. === When I do a move, I got "Move recorded, waiting for update ..." forever === "Move recorded" means that your ajaxcall request has been sent to the server and returned normally. "Waiting for update" means that your client interface is waiting for some notifications from the server that correspond to the move we just did. If this message stays forever, it is probably that your PHP code does not send any notification when the move happens, which is abnormal. To fix this: add a notifyAllPlayers or a notifyPlayer call in your PHP code. === Some player action is triggered randomly when I click somewhere on the game area === You probably used "dojo.connect" on a null object. In this case, dojo.connect associate the event (ex: "onclick") to the whole game area. Most of the time it happens in this situation, when my_object element does not exists: <pre> dojo.connect( $("my_object"), "onclick", this, function() { ... } </pre> To determine if this is the case, place "alert( $("my_object") )" before the dojo.connect to check if the object exists or not. === Javascript does not know how to sum two numbers === Be careful when you manipulate integers returned by notifications: most of the time, Javascript considers they are Strings and not Integers. As a result: <pre> var i=1; i += notif.args.increment; // With notif.args.increment='1' alert( i ); // i=11 instead of 2 !! Javascript concatenate 2 strings ! </pre> To solve this, to hesitate to use the "toint" function: <pre> var i=1; i += toint( notif.args.increment ); // With notif.args.increment='1' alert( i ); // i=2 :) </pre> === Javascript: do not use substr with negative numbers === To get the last characters of a string, use "slice" instead of "substr" which has a bug on IE: <pre> var three_last_characters = string.substr( -3 ); // Wrong var three_last_characters = string.slice( -3 ); // Correct </pre> cf42daf00fb7be404a4a30ec9f179847d5a069cc Game database model: dbmodel.sql 0 92 601 490 2013-01-30T13:44:45Z Sourisdudesert 1 /* Default tables */ wikitext text/x-wiki In this file you specify the database schema of your game. This file contains SQL queries that will be executed during the creation of your game table. Note: you can't change the database schema during the game. == Create your schema == To build this file, we recommend you to build the tables you need with the PhpMyAdmin tool (see BGA user guide), and then to export them and to copy/paste the content inside this file. == Default tables == Important: by default, BGA creates 4 tables for your game: global, stats, gamelog, and player. You must not modify the schema of global, stats and gamelog tables (and you must not access them directly with SQL queries in your PHP code). You may add columns to "player" table. This is very practical to add simple values associated with players. Example: <pre> ALTER TABLE `player` ADD `player_reserve_size` SMALLINT UNSIGNED NOT NULL DEFAULT '7'; </pre> For your information, the useful columns of default "player" table are: * player_no: the index of player in natural playing order. * player_id * player_name: (note: you should better access this date with getActivePlayerName() or loadPlayersBasicInfos() methods) * player_score: the current score of the player (displayed in the player panel). You must update this field to update player's scores. * player_score_aux: the secondary score, used as a tie breaker. You must update this field according to tie breaking rules of the game (see also: [[Main_game_logic:_yourgamename.game.php#Manage_player_scores_and_Tie_breaker|Manage_player_scores_and_Tie_breaker]]) 55928f7428de62d98335489cb1b48e7a5e837ad4 Game layout: view and template: yourgamename.view.php and yourgamename yourgamename.tpl 0 98 602 570 2013-01-30T13:51:18Z Sourisdudesert 1 /* Javascript templates */ wikitext text/x-wiki These 2 files work together to provide the HTML layout of your game. Using these 2 files, you specify what HTML is rendered in your game client interface. In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser. Example: extract of "hearts_hearts.tpl": <pre> <div id="myhand_wrap" class="whiteblock"> <h3>{MY_HAND}</h3> <div id="myhand"> </div> </div> </pre> == WARNING == Your view and your template are supposed to generate only the BASE layout of the game You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :) Example of things to generate in your view: * The overall layout of your game interface (what is displayed where). * The board and fixed elements on the board (ex: places for cards, squares, ...). Example of things that shouldn't be generate by your view: * Game elements that come and go from the game area. * Game elements that are moving from one place to another. == phplib template system == BGA is using the phplib template system, used for example in PHPbb forums. More details about how to use phplib template system here: http://www.phpbuilder.com/columns/david20000512.php3 == Variables == In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value. In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}". To give a value to this variable in your view.php: Examples: <pre> // Display a translated version of "My hand" at the place of the variable in the template $this->tpl['MY_HAND'] = self::_("My hand"); // Display some raw HTML material at the place of the variable $this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" ); </pre> == Blocks == Using "blocks", you can repeat a piece of HTML from your template several time. You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares: <pre> (in reversi_reversi.tpl) <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> <div id="discs"> </div> </div> (in reversi.view.php) $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Explanations: * You specify a block in your template file, using "BEGIN" and "END" keywords. In the example above, we are creating a block named "square". * In your view, you declare your block using "begin_block" method. * Then, you can insert as many block as you want to, using "insert_block" method. The insert_block method takes 2 parameters: * the name of the block to insert. * an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP). == Nested blocks == You can use nested blocks. In the example below, we are going to add a mini-board for each player of the game, with 4 card places on each of it: <pre> (In template file) <!-- BEGIN player --> <div class="miniboard" id="miniboard_{PLAYER_ID}"> <div class="card_places"> <!-- BEGIN card_place --> <div id="card_place_{PLAYER_ID}_{PLACE_ID}"> </div> <!-- END card_place --> </div> </div> <!-- END player --> (In view file) $this->page->begin_block( "mygame_mygame.tpl", "card_place" ); // Nested block must be declared first $this->page->begin_block( "mygame_mygame.tpl", "player" ); foreach( $players as $player_id => $player ) { // Important: nested block must be reset here, otherwise the second player miniboard will // have 8 card_place, the third will have 12 card_place, and so one... $this->page->reset_subblocks( 'card_place' ); for( $i=1; $i<=4; $i++ ) { $this->page->insert_block( "card_place", array( 'PLAYER_ID' => $player_id, 'PLACE_ID' => $i ); } $this->page->insert_block( 'player', array( 'PLAYER_ID' => $player_id ); } </pre> == Javascript templates == For game elements that come and go from the game area, we suggest you to define a Javascript template. A Javascript template is defined in your template file like this: (Reversi Token from Reversi example): <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: a section for javascript templates is already available at the end of your template skeleton file. Then, you can use this javascript template to insert this piece of HTML in your game interface, like this: <pre> dojo.place( this.format_block( 'jstpl_disc', { xy: x+''+y, color: color } ) , 'discs' ); </pre> == How to access game information from .view.php? == From your .view.php, you can access the following: === Access current player id=== <pre> global $g_user; $current_player_id = $g_user->get_id(); </pre> === Access game object === In your view file, "$this->game" contains an instance of your main game class. Example: <pre> // Access to some game elements description described in your "material.inc.php": $my_cards_types = $this->game->card_types; // Access to any (public) method defined in my .game.php file: $result = $this->game->myMethod(); </pre> a1db3a68a1c6b558482b31c4766efcb3c6170a16 Translations 0 94 603 534 2013-01-30T14:00:36Z Sourisdudesert 1 /* Focus on translating notifications */ wikitext text/x-wiki Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them. == How translation works? == When developing your game, all strings must be in English. Strings must be coherent with the English version of the game. Before the release of the game, BGA team will do the French translation of the game. After the release of the game, the BGA players community will translate the game in every language. == What should be translated? == Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ... This does NOT include error messages that are not supposed to happened (unexpected errors). == Focus on translating notifications == Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function. However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side. == WARNING: how to make sure your strings will be translated == For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers). If your original string is not "physically" inside one of this marker, it won't be translated. <pre> // Examples: the following strings will be translated: var mystring_translated = _("my string"); // JS $mystring_translated = self::_("my string"); // PHP $mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP // Examples: the following strings WILL NOT be translated: $my_string = "my string"; $not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation $not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing </pre> == On client side (Javascript) == On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate. Examples: <pre> // Get a string in player's language: var translated = _("original english string"); // Get a string in player's language with parameter: var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", { p: 2, d: 4 } ); </pre> Note: what is also possible to do is == On server side (PHP) == On PHP side, you can use 3 different functions to specify that a string must be translated. '''clienttranslate( "my string to translate" ):''' This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side. In general, you use clienttranslate: * On your states.inc.php, for field "description" and "descriptionmyturn". <pre> "description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'), </pre> * On "material.inc.php", when defining texts for game material that must be displayed on client side. <pre> $this->card_types = array( 1 => array( 'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side. </pre> * When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation. <pre> // A game log string with no argument: self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() ); </pre> Translating arguments is a little bit more complex. It is using the "i18n" special argument as below: <pre> // In the following example, we translate the game log itself, but also the "card_name" argument: self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array( 'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'points' => $points, 'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string. ) ); </pre> '''self::_( "my string to translate" ):''' This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player). Most of the time, you don't need to translate strings on server side, except on the following 3 situations: * When throwing an exception because the player did a forbidden move. <pre> // This will display a translatable red message to the player that just do some wrong action: throw new feException( self::_('You must choose 3 cards'), true); // ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated. </pre> * In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file. <pre> $this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II"); </pre> * Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions. <pre> // In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this: throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true ); </pre> * Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user. '''totranslate( "my string to translate" ):''' This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side. You should not use this function, except on the following cases: * Statistics name in stats.inc.php * Option names and option values name in gameoptions.inc.php 00b876af979e40df1604bdaf14081b503740bd63 604 603 2013-01-30T14:08:44Z Sourisdudesert 1 /* WARNING: how to make sure your strings will be translated */ wikitext text/x-wiki Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them. == How translation works? == When developing your game, all strings must be in English. Strings must be coherent with the English version of the game. Before the release of the game, BGA team will do the French translation of the game. After the release of the game, the BGA players community will translate the game in every language. == What should be translated? == Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ... This does NOT include error messages that are not supposed to happened (unexpected errors). == Focus on translating notifications == Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function. However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side. == WARNING: how to make sure your strings will be translated == For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers). If your original string is not "physically" inside one of this marker, it won't be translated. <pre> // Examples: the following strings will be translated: var mystring_translated = _("my string"); // JS $mystring_translated = self::_("my string"); // PHP $mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP // Examples: the following strings WILL NOT be translated: $my_string = "my string"; $not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation $not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing </pre> == How to not make translators crazy ;) == * When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings. * Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it). * Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like: <pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre> Write instead: <pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre> (or the equivalent "dojo.string.substitute" in Javascript) * When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short string. == On client side (Javascript) == On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate. Examples: <pre> // Get a string in player's language: var translated = _("original english string"); // Get a string in player's language with parameter: var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", { p: 2, d: 4 } ); </pre> Note: what is also possible to do is == On server side (PHP) == On PHP side, you can use 3 different functions to specify that a string must be translated. '''clienttranslate( "my string to translate" ):''' This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side. In general, you use clienttranslate: * On your states.inc.php, for field "description" and "descriptionmyturn". <pre> "description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'), </pre> * On "material.inc.php", when defining texts for game material that must be displayed on client side. <pre> $this->card_types = array( 1 => array( 'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side. </pre> * When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation. <pre> // A game log string with no argument: self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() ); </pre> Translating arguments is a little bit more complex. It is using the "i18n" special argument as below: <pre> // In the following example, we translate the game log itself, but also the "card_name" argument: self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array( 'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'points' => $points, 'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string. ) ); </pre> '''self::_( "my string to translate" ):''' This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player). Most of the time, you don't need to translate strings on server side, except on the following 3 situations: * When throwing an exception because the player did a forbidden move. <pre> // This will display a translatable red message to the player that just do some wrong action: throw new feException( self::_('You must choose 3 cards'), true); // ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated. </pre> * In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file. <pre> $this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II"); </pre> * Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions. <pre> // In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this: throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true ); </pre> * Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user. '''totranslate( "my string to translate" ):''' This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side. You should not use this function, except on the following cases: * Statistics name in stats.inc.php * Option names and option values name in gameoptions.inc.php 6f088dd77b603414b4986ec781e0714c6b6ca381 605 604 2013-01-30T14:09:03Z Sourisdudesert 1 /* How to not make translators crazy ;) */ wikitext text/x-wiki Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them. == How translation works? == When developing your game, all strings must be in English. Strings must be coherent with the English version of the game. Before the release of the game, BGA team will do the French translation of the game. After the release of the game, the BGA players community will translate the game in every language. == What should be translated? == Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ... This does NOT include error messages that are not supposed to happened (unexpected errors). == Focus on translating notifications == Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function. However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side. == WARNING: how to make sure your strings will be translated == For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers). If your original string is not "physically" inside one of this marker, it won't be translated. <pre> // Examples: the following strings will be translated: var mystring_translated = _("my string"); // JS $mystring_translated = self::_("my string"); // PHP $mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP // Examples: the following strings WILL NOT be translated: $my_string = "my string"; $not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation $not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing </pre> == How to not make translators crazy ;) == * When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings. * Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it). * Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like: <pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre> Write instead: <pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre> (or the equivalent "dojo.string.substitute" in Javascript) * When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings. == On client side (Javascript) == On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate. Examples: <pre> // Get a string in player's language: var translated = _("original english string"); // Get a string in player's language with parameter: var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", { p: 2, d: 4 } ); </pre> Note: what is also possible to do is == On server side (PHP) == On PHP side, you can use 3 different functions to specify that a string must be translated. '''clienttranslate( "my string to translate" ):''' This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side. In general, you use clienttranslate: * On your states.inc.php, for field "description" and "descriptionmyturn". <pre> "description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'), </pre> * On "material.inc.php", when defining texts for game material that must be displayed on client side. <pre> $this->card_types = array( 1 => array( 'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side. </pre> * When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation. <pre> // A game log string with no argument: self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() ); </pre> Translating arguments is a little bit more complex. It is using the "i18n" special argument as below: <pre> // In the following example, we translate the game log itself, but also the "card_name" argument: self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array( 'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'points' => $points, 'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string. ) ); </pre> '''self::_( "my string to translate" ):''' This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player). Most of the time, you don't need to translate strings on server side, except on the following 3 situations: * When throwing an exception because the player did a forbidden move. <pre> // This will display a translatable red message to the player that just do some wrong action: throw new feException( self::_('You must choose 3 cards'), true); // ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated. </pre> * In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file. <pre> $this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II"); </pre> * Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions. <pre> // In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this: throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true ); </pre> * Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user. '''totranslate( "my string to translate" ):''' This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side. You should not use this function, except on the following cases: * Statistics name in stats.inc.php * Option names and option values name in gameoptions.inc.php 5342d4acfd2ce7de3b9b024bdee754ec12cbe55f 606 605 2013-01-30T14:11:52Z Sourisdudesert 1 /* How to not make translators crazy ;) */ wikitext text/x-wiki Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them. == How translation works? == When developing your game, all strings must be in English. Strings must be coherent with the English version of the game. Before the release of the game, BGA team will do the French translation of the game. After the release of the game, the BGA players community will translate the game in every language. == What should be translated? == Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ... This does NOT include error messages that are not supposed to happened (unexpected errors). == Focus on translating notifications == Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function. However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side. == WARNING: how to make sure your strings will be translated == For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers). If your original string is not "physically" inside one of this marker, it won't be translated. <pre> // Examples: the following strings will be translated: var mystring_translated = _("my string"); // JS $mystring_translated = self::_("my string"); // PHP $mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP // Examples: the following strings WILL NOT be translated: $my_string = "my string"; $not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation $not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing </pre> == How to not make translators crazy ;) == * When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings. * Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it). * Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like: <pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre> Write instead: <pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre> (or the equivalent "dojo.string.substitute" in Javascript) * When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings. * The BGA translation policy is to be flexible on grammar... We prefer to write "player gets 1 coin(s)" than write two versions of the same string for plural and singular - it reduces the number of strings to translate. == On client side (Javascript) == On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate. Examples: <pre> // Get a string in player's language: var translated = _("original english string"); // Get a string in player's language with parameter: var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", { p: 2, d: 4 } ); </pre> Note: what is also possible to do is == On server side (PHP) == On PHP side, you can use 3 different functions to specify that a string must be translated. '''clienttranslate( "my string to translate" ):''' This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side. In general, you use clienttranslate: * On your states.inc.php, for field "description" and "descriptionmyturn". <pre> "description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'), </pre> * On "material.inc.php", when defining texts for game material that must be displayed on client side. <pre> $this->card_types = array( 1 => array( 'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side. </pre> * When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation. <pre> // A game log string with no argument: self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() ); </pre> Translating arguments is a little bit more complex. It is using the "i18n" special argument as below: <pre> // In the following example, we translate the game log itself, but also the "card_name" argument: self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array( 'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'points' => $points, 'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string. ) ); </pre> '''self::_( "my string to translate" ):''' This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player). Most of the time, you don't need to translate strings on server side, except on the following 3 situations: * When throwing an exception because the player did a forbidden move. <pre> // This will display a translatable red message to the player that just do some wrong action: throw new feException( self::_('You must choose 3 cards'), true); // ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated. </pre> * In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file. <pre> $this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II"); </pre> * Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions. <pre> // In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this: throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true ); </pre> * Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user. '''totranslate( "my string to translate" ):''' This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side. You should not use this function, except on the following cases: * Statistics name in stats.inc.php * Option names and option values name in gameoptions.inc.php 437b64de7275fe16f6a09023d10a92b7ab0303b2 Game interface logic: yourgamename.js 0 88 607 572 2013-01-30T14:12:52Z Sourisdudesert 1 wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player f4a705f0f672ce8dddadba6c9f4d613dd937ae54 608 607 2013-01-30T14:21:47Z Sourisdudesert 1 /* Notifications */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 9a8fdfb42e8b8eb4ec315d1daf3cb4d45f9e680d 609 608 2013-01-30T14:27:59Z Sourisdudesert 1 /* Subscribe to notifications */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName == Animations == ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 4c7fc3933a944503c6d3bffcdd3a28fe399ce52c 610 609 2013-01-30T14:43:43Z Sourisdudesert 1 /* Animations */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player ceee517a59f3dc740a50da1f396cfc171f5e8cf3 611 610 2013-01-30T14:51:01Z Sourisdudesert 1 /* Animations */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 9b8fb6b0cdfd751a4df6d848620ba468d2c8bcc2 612 611 2013-01-30T14:52:08Z Sourisdudesert 1 /* Animations */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player ff91a04387ccb6ce0a83b2057d73d2f3b02aceb2 613 612 2013-01-30T14:58:55Z Sourisdudesert 1 /* Animations */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player f113c6f0688a5c8675268b06b776a472e8e296e6 614 613 2013-01-30T15:00:13Z Sourisdudesert 1 /* Animations */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 8a38d623f326ef8eba093681c87adc036cbbcc11 615 614 2013-01-30T15:07:09Z Sourisdudesert 1 /* Moving elements */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player f585ef408be1bd33f808044adf1ccf799dc50695 616 615 2013-01-30T15:08:50Z Sourisdudesert 1 /* Other useful stuff */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 8b08708d91b15ed204ebd2b648b54676117e1b7d 617 616 2013-01-30T15:08:59Z Sourisdudesert 1 /* General tips */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 34566293e7a72a0b6122ff14fd675a9a43dc1aa2 618 617 2013-01-30T15:19:59Z Sourisdudesert 1 /* Other useful stuff */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 412a63f4c33407628ed1d60a616f31f7c8f1cc43 619 618 2013-01-30T15:20:36Z Sourisdudesert 1 wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] 1c8e0371e586802deb58127e413bdc5396e52fec 620 619 2013-01-30T15:20:52Z Sourisdudesert 1 /* Other useful stuff */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] b36c6cc0e7326219304189b189b0bc902479c611 621 620 2013-01-30T15:22:21Z Sourisdudesert 1 /* Dialogs, warning messages, confirmation dialogs, ... */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] 26121d2968fe9d01fe23fe8daff1cf93e815eeaa 622 621 2013-01-30T15:30:44Z Sourisdudesert 1 /* Dialogs, warning messages, confirmation dialogs, ... */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] da65aad9c96ea34a94096025ba4eb7d0ade5f6d6 623 622 2013-01-30T15:38:14Z Sourisdudesert 1 /* Dialogs, warning messages, confirmation dialogs, ... */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: === Scoring dialogs === TODO == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] 065726dd9b1f8325cdbbf4cceabb97f1869edd0a 624 623 2013-01-30T15:41:40Z Sourisdudesert 1 /* Dialogs */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); </pre> === Scoring dialogs === TODO == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] fb2368d30850f91de0df598317f17804ad420937 625 624 2013-01-30T15:43:40Z Sourisdudesert 1 /* Dialogs */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> === Scoring dialogs === TODO == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] 4de87503c1d29276dafd667781f2d379528e7581 626 625 2013-01-30T15:45:40Z Sourisdudesert 1 /* Dialogs */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === TODO == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] 65ee871aec9432a99069caac08f4127d8ca0d83d 627 626 2013-01-30T15:48:21Z Sourisdudesert 1 /* Scoring dialogs */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] 370fe31d6e015e611d22df85d8b741b7c9e7ea13 628 627 2013-01-30T16:09:54Z Sourisdudesert 1 /* Scoring dialogs */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] 91ac3f1c2bed80d7d77eae390f6293ca4b66848f 629 628 2013-01-30T16:12:45Z Sourisdudesert 1 /* BGA GUI components */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 3cdee1e01b47aa1e56b73b29b4d01a823ae07118 644 629 2013-02-12T12:22:39Z Sourisdudesert 1 /* General tips */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 4724100d9aa96ce01e65d3b388664799dde876b1 Stock 0 97 633 559 2013-02-02T08:55:38Z Sourisdudesert 1 /* Complete stock component reference */ wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: _ type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. _ weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted). _ image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_themeurl+'img/your_game_name/yourimage.png' </pre> _ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. 16282ee586f0e8c2046670ca09ab3d2e371cf099 643 633 2013-02-12T12:11:45Z Sourisdudesert 1 /* Complete stock component reference */ wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: _ type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. _ weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted). _ image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_themeurl+'img/your_game_name/yourimage.png' </pre> _ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. '''onItemCreate''' Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it. Complete example: <pre> // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item: this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); (...) // And here is our "setupNewCard": setupNewCard: function( card_div, card_type_id, card_id ) { // Add a special tooltip on the card: this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' ); // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type // Add some custom HTML content INSIDE the Stock item: dojo.place( this.format_block( 'jstpl_my_card_content', { .... } ), card_div.id ); } </pre> 47c1cb6415f093e75bceb1a338885062667c2054 Game interface stylesheet: yourgamename.css 0 96 634 520 2013-02-04T14:48:42Z Sourisdudesert 1 wikitext text/x-wiki This is the CSS stylesheet of your game User Interface. Styles defined on this file will be applied to the HTML elements you define in your HTML template (yourgame_yourgame.tpl), and to HTML elements you create dynamically with Javascript. Usually, you are using CSS to: 1°) define the overall layout of your game (ex: place the board on the top left, place player's hand beside, place the deck on the right, ...). 2°) create your CSS-sprites: All images of your games should be gathered into a small number of image files. Then, using background-image and background-position CSS properties, you create HTML blocks that can display these images correctly. Example: <pre> Example of CSS sprites (a black token and a white token, 20x20px each, embedded in the same "tokens.png" 40x20px image): .white_token { background-image: url('../../img/emptygame/tokens.png'); background-position: 0px 0px; } .black_token { background-image: url('../../img/emptygame/tokens.png'); background-position: -20px 0px; } .token { width: 20px; height: 20px; background-repeat: none; } </pre> 3°) ... anything else: It is really easy to add and remove CSS classes dynamically from your Javascript with dojo.addClass and dojo.removeClass. It is also easy to check if an element has a class (dojo.hasClass) or to get all elements with a specific class (dojo.query). This is why, very often, using CSS classes for the logic of your user interface allow you to do complex thing easily. Note: on the production platform, this file will be compressed and comments will be removed. Consequently, don't hesitate to put as many comments as necessary. Important: ALL the CSS directives for your game must be included in this CSS file. You can't create additional CSS files and import them. 9820cd9a56bfee0746b394fc31f1382787b601a5 Gamehelpcantstop 0 35 635 170 2013-02-07T04:14:07Z Karl 2334 wikitext text/x-wiki Can't Stop is a very easy and fast game! '''How to play''' Roll 4 standard dice and then choose the sums of any 2 dice to advance your position on the board. You are allowed to use 3 temporary markers to track your progress in columns marked 2 through 12. These markers are commonly white or black. You can continue to roll the dice hoping to roll one of the previous combinations in the three columns selected this turn. When you think you've pushed your luck far enough you say "STOP" then pass the dice to the next player and replace the white markers with your own. If you roll the dice and find no useful combination you fail and your progress is lost. The more common numbers on 2d6 (6,7 and 8) have more steps in their paths while the less common combinations (2 and 12) have fewer. '''The object of the game is''' to reach and cover 3 peaks of these columns! 欲罷不能 如何進行遊戲 首先擲出四顆骰子,之後把四顆骰子兩兩分組配成可以搭配的任意數字(2~12),之後選擇其中一種配對執行。 執行時你可以擁有三個暫時的標記物可以作為前進的工具(此回合超過第三個就不能選該組合中的該項數值,但是其中一項可以前進即可選擇,另外一總組合則視同放棄) 重複以上動作直到你覺得這回合你前進已經夠了或是擲出你沒有辦法前進的骰子點數組合則該回合結束 若是自己喊出「夠了」則在現有的暫時標記物的位置換成自己的標記物輪下一人進行 若是因為擲出不能前進的骰子組合則是本回合前進的格數全部作廢依然換下一人進行回合 遊戲中使用的是兩個六面骰,依照組合的出現機率不同,在不同組合上要攻頂的需求步數也不同(例如7就需要最多格,因為他的出現率最高,相對的比較難出現的2.12就只需要短短的三格) 遊戲獲勝條件是其中有一人佔領了三條路線後則遊戲結束,由佔領三條路線的人獲勝 eb25daa5eaeda4fa4f83b74e41bcddcae0491261 Deck 0 101 636 2013-02-11T16:56:57Z Sourisdudesert 1 Created page with ""Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side. Using "deck", you will be able to use the following fea..." wikitext text/x-wiki "Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side. Using "deck", you will be able to use the following features without writing a single SQL database request: * Place cards in pile, shuffle cards, draw cards one by one or many by many. * "Auto-reshuffle" discard pile into deck when deck is empty. * Move cards between different locations: hands of players, the table, ... 99108eb430d4ddf064ecc1abd63107dd0fa58251 637 636 2013-02-11T17:05:25Z Sourisdudesert 1 wikitext text/x-wiki "Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side. Using "deck", you will be able to use the following features without writing a single SQL database request: * Place cards in pile, shuffle cards, draw cards one by one or many by many. * "Auto-reshuffle" discard pile into deck when deck is empty. * Move cards between different locations: hands of players, the table, ... == Using Deck: Hearts example == Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times. == Deck general principles == For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql": <pre> CREATE TABLE IF NOT EXISTS `card` ( `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `card_type` varchar(16) NOT NULL, `card_type_arg` int(11) NOT NULL, `card_location` varchar(16) NOT NULL, `card_location_arg` int(11) NOT NULL, PRIMARY KEY (`card_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method: <pre> $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); </pre> Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game). 3fe6de7e682508ff987b79aa27af2393f512b96d 638 637 2013-02-11T17:23:59Z Sourisdudesert 1 /* Deck general principles */ wikitext text/x-wiki "Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side. Using "deck", you will be able to use the following features without writing a single SQL database request: * Place cards in pile, shuffle cards, draw cards one by one or many by many. * "Auto-reshuffle" discard pile into deck when deck is empty. * Move cards between different locations: hands of players, the table, ... == Using Deck: Hearts example == Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times. == Deck overview == With Deck component, you manage all cards of your game. Using Deck component, each card will have 5 properties: * '''id''': This is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game. * '''type''' and '''type_arg''': These two values defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. Examples of usage of "type" and "type_arg": * In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K). * In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used. * In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile. For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql": <pre> CREATE TABLE IF NOT EXISTS `card` ( `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `card_type` varchar(16) NOT NULL, `card_type_arg` int(11) NOT NULL, `card_location` varchar(16) NOT NULL, `card_location_arg` int(11) NOT NULL, PRIMARY KEY (`card_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method: <pre> $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); </pre> Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game). Afterwards, we can start using our "Deck" object. In general, the first 5b42f3001a9bbf08e8e856a5d573d6ffd80ed60b 639 638 2013-02-11T17:35:46Z Sourisdudesert 1 /* Deck overview */ wikitext text/x-wiki "Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side. Using "deck", you will be able to use the following features without writing a single SQL database request: * Place cards in pile, shuffle cards, draw cards one by one or many by many. * "Auto-reshuffle" discard pile into deck when deck is empty. * Move cards between different locations: hands of players, the table, ... == Using Deck: Hearts example == Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times. == Deck overview == With Deck component, you manage all cards of your game. === The 5 properties of each card === Using Deck component, each card will have 5 properties: * '''id''': This is the unique ID of each card. * '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?). * '''location''' and '''location_arg''': These two values defines where is the card at now. id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area. '''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game. '''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below. Examples of usage of "type" and "type_arg": * In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K). * In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used. * In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile. '''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer. You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs: * 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn). * 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player. * 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle"). Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game. === Create a new Deck component === For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql": <pre> CREATE TABLE IF NOT EXISTS `card` ( `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `card_type` varchar(16) NOT NULL, `card_type_arg` int(11) NOT NULL, `card_location` varchar(16) NOT NULL, `card_location_arg` int(11) NOT NULL, PRIMARY KEY (`card_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method: <pre> $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); </pre> Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game). Afterwards, we can start using our "Deck" object. In general, the first dbeb5611d5db3a1ebe6fe5ed93f5151f1197b857 640 639 2013-02-11T17:39:39Z Sourisdudesert 1 /* Create a new Deck component */ wikitext text/x-wiki "Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side. Using "deck", you will be able to use the following features without writing a single SQL database request: * Place cards in pile, shuffle cards, draw cards one by one or many by many. * "Auto-reshuffle" discard pile into deck when deck is empty. * Move cards between different locations: hands of players, the table, ... == Using Deck: Hearts example == Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times. == Deck overview == With Deck component, you manage all cards of your game. === The 5 properties of each card === Using Deck component, each card will have 5 properties: * '''id''': This is the unique ID of each card. * '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?). * '''location''' and '''location_arg''': These two values defines where is the card at now. id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area. '''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game. '''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below. Examples of usage of "type" and "type_arg": * In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K). * In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used. * In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile. '''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer. You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs: * 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn). * 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player. * 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle"). Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game. === Create a new Deck component === For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql": <pre> CREATE TABLE IF NOT EXISTS `card` ( `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `card_type` varchar(16) NOT NULL, `card_type_arg` int(11) NOT NULL, `card_location` varchar(16) NOT NULL, `card_location_arg` int(11) NOT NULL, PRIMARY KEY (`card_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method: <pre> $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); </pre> Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game). Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method. "Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts": <pre> // Create cards $cards = array(); foreach( $this->colors as $color_id => $color ) // spade, heart, diamond, club { for( $value=2; $value<=14; $value++ ) // 2, 3, 4, ... K, A { $cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1); } } $this->cards->createCards( $cards, 'deck' ); </pre> As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument). bf27635292e5f1fa021037833d79d2eb48e3c25a 641 640 2013-02-11T17:46:47Z Sourisdudesert 1 /* Create a new Deck component */ wikitext text/x-wiki "Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side. Using "deck", you will be able to use the following features without writing a single SQL database request: * Place cards in pile, shuffle cards, draw cards one by one or many by many. * "Auto-reshuffle" discard pile into deck when deck is empty. * Move cards between different locations: hands of players, the table, ... == Using Deck: Hearts example == Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times. == Deck overview == With Deck component, you manage all cards of your game. === The 5 properties of each card === Using Deck component, each card will have 5 properties: * '''id''': This is the unique ID of each card. * '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?). * '''location''' and '''location_arg''': These two values defines where is the card at now. id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area. '''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game. '''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below. Examples of usage of "type" and "type_arg": * In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K). * In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used. * In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile. '''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer. You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs: * 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn). * 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player. * 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle"). Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game. === Create a new Deck component === For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql": <pre> CREATE TABLE IF NOT EXISTS `card` ( `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `card_type` varchar(16) NOT NULL, `card_type_arg` int(11) NOT NULL, `card_location` varchar(16) NOT NULL, `card_location_arg` int(11) NOT NULL, PRIMARY KEY (`card_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method: <pre> $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); </pre> Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game). Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method. "Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts": <pre> // Create cards $cards = array(); foreach( $this->colors as $color_id => $color ) // spade, heart, diamond, club { for( $value=2; $value<=14; $value++ ) // 2, 3, 4, ... K, A { $cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1); } } $this->cards->createCards( $cards, 'deck' ); </pre> As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument). Now, you are ready to use "Deck"! === Simple examples using Deck === (Most examples are from "Hearts" game) <pre> // In "getAllDatas', we need to send to the current player all the cards he has in hand: $result['hand'] = $this->cards->getCardsInLocation( 'hand', $player_id ); </pre> <pre> // At some time we want to check if all the cards (52) are in player's hands: if( $this->cards->countCardInLocation( 'hand' ) == 52 ) // do something </pre> <pre> // When a player plays a card in front of him on the table: $this->cards->moveCard( $card_id, 'cardsontable', $player_id ); // Note the use of the custom location 'cardsontable' here to keep track of cards on the table. </pre> <pre> // This is a new hand: let's gather all cards from everywhere in the deck: $this->cards->moveAllCardsInLocation( null, "deck" ); // And then shuffle the deck $this->cards->shuffle( 'deck' ); // And then deal 13 cards to each player // Deal 13 cards to each players // Create deck, shuffle it and give 13 initial cards $players = self::loadPlayersBasicInfos(); foreach( $players as $player_id => $player ) { $cards = $this->cards->pickCards( 13, 'deck', $player_id ); // Notify player about his cards self::notifyPlayer( $player_id, 'newHand', '', array( 'cards' => $cards ) ); } // Note the use of "notifyPlayer" instead of "notifyAllPlayers": new cards is a private information ;) </pre> d01c941c833ffd3e1318e0ad694112c6c46f2afa Main game logic: yourgamename.game.php 0 86 642 590 2013-02-12T11:54:45Z Sourisdudesert 1 /* Notify players */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this: <pre> $this->tie_breaker_description = self::_("Describe here your tie breaker formula"); </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. 435c6857bd4d2b9828f2721bd88716e2c3c77355 Gamehelptroyes 0 26 645 54 2013-02-13T16:04:43Z Peach 2372 /* Ziel */ wikitext text/x-wiki == Ziel == Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels. == Rules summary == (This rules summary is based on the game help written by [http://boardgamegeek.com/user/pregremlin Andrew Agard] for Board Game Geek, under Creative Commons license. Please see [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] here for details. Thank you Andrew !) ===Initial Placement=== * In clockwise order place a citizen in empty space of one building * Continue in counter clockwise order from last player and so on until all citizens placed ===Game play=== ====Phase 0: Reveal the Activity cards==== Reveal activity card for each color corresponding to current round (first 3 rounds only) ====Phase 1: Income and salaries==== Receive 10 deniers and pay 1 per Bishopric and 2 per Palace citizen or lose 2 VP ====Phase 2: Assembling the workforce==== Roll yellow/white/red die per citizen in City Hall/Bishopric/Palace and place in district ====Phase 3: Events==== Reveal top red and white or yellow Event and place to right of queue (unlimited Events) Events take effect from left to right * Military: start player takes 1 black die per die symbol * Other events: see annex (can’t execute: execute as much as possible and lose 2 VP) After Events, roll black dice and counter: * Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once * Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP) * In order players must counter highest remaining until all countered * Use any color dice. Double red dice. Can’t buy dice or use activity cubes ====Phase 4: Actions==== See below. ====Phase 5: End of the round==== Receive deniers from district Return citizens lying on buildings to personal supplies Return unused dice to general supply Pass start player card left. ===Actions=== In order each player can use 1-3 matching dice for one action or pass. Round ends when no dice available or all players have passed May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice ====Activate Activity Card==== Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place citizen on free space (or illustration if full) from personal supply or any board location * 1 tradesman per player per card * Must activate at least once if tradesman hired * Citizens on card cannot be moved to newly freed space Immediate effect: activation cost (round down) determines color and use of dice Delayed effect: place cubes equal to activation cost. Use later (one cube per action) ====Construct Cathedral==== * Use 1-3 white dice to place 1-3 cubes on same-numbered construction site * Must place on lower levels before placing in higher levels for each set of valued spaces * Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6 ====Combat Events==== * Activation cost (round down) defines dice and number of cubes to place on card * Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners Event countered when banners filled * Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards. * 2nd most cubes earns smaller reward (tied: total rounded down) * Most cubes takes card (tied: player who placed first). Discard if neutral has most * Marauding: rewards given, cubes removed, and then event is available again ====Place a citizen on building==== * Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value * Shift existing citizens to right. Citizens pushed off are laid on building illustration * If already have expelled citizen nobody can expel your citizens from that building ====Use Agriculture==== * Gain number of deniers equal to total value divided by 2 (round down) ===Pass=== * If dice still in any city square, pass and receive 2 deniers which are placed in district * Each turn add another denier to district Have a good game ! cac908b237e45cd5a4647769f0b295e42d37c72e 646 645 2013-02-13T16:26:08Z Peach 2372 /* Regel Zusammenfassung */ wikitext text/x-wiki == Ziel == Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels. == Regel Zusammenfassung == (Diese Regel Zusammenfassung basiert auf der Spielhilfe von [http://boardgamegeek.com/user/pregremlin Andrew Agard] für Board Game Geek, unter Creative Commons Lizenz. Bitte schauen Sie [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] hier für Details. Vielen Dank Andrew !) ===Initial Placement=== * In clockwise order place a citizen in empty space of one building * Continue in counter clockwise order from last player and so on until all citizens placed ===Spielablauf=== ====Phase 0: Reveal the Activity cards==== Reveal activity card for each color corresponding to current round (first 3 rounds only) ====Phase 1: Income and salaries==== Receive 10 deniers and pay 1 per Bishopric and 2 per Palace citizen or lose 2 VP ====Phase 2: Assembling the workforce==== Roll yellow/white/red die per citizen in City Hall/Bishopric/Palace and place in district ====Phase 3: Events==== Reveal top red and white or yellow Event and place to right of queue (unlimited Events) Events take effect from left to right * Military: start player takes 1 black die per die symbol * Other events: see annex (can’t execute: execute as much as possible and lose 2 VP) After Events, roll black dice and counter: * Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once * Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP) * In order players must counter highest remaining until all countered * Use any color dice. Double red dice. Can’t buy dice or use activity cubes ====Phase 4: Actions==== See below. ====Phase 5: End of the round==== Receive deniers from district Return citizens lying on buildings to personal supplies Return unused dice to general supply Pass start player card left. ===Actions=== In order each player can use 1-3 matching dice for one action or pass. Round ends when no dice available or all players have passed May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice ====Activate Activity Card==== Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place citizen on free space (or illustration if full) from personal supply or any board location * 1 tradesman per player per card * Must activate at least once if tradesman hired * Citizens on card cannot be moved to newly freed space Immediate effect: activation cost (round down) determines color and use of dice Delayed effect: place cubes equal to activation cost. Use later (one cube per action) ====Construct Cathedral==== * Use 1-3 white dice to place 1-3 cubes on same-numbered construction site * Must place on lower levels before placing in higher levels for each set of valued spaces * Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6 ====Combat Events==== * Activation cost (round down) defines dice and number of cubes to place on card * Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners Event countered when banners filled * Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards. * 2nd most cubes earns smaller reward (tied: total rounded down) * Most cubes takes card (tied: player who placed first). Discard if neutral has most * Marauding: rewards given, cubes removed, and then event is available again ====Place a citizen on building==== * Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value * Shift existing citizens to right. Citizens pushed off are laid on building illustration * If already have expelled citizen nobody can expel your citizens from that building ====Use Agriculture==== * Gain number of deniers equal to total value divided by 2 (round down) ===Pass=== * If dice still in any city square, pass and receive 2 deniers which are placed in district * Each turn add another denier to district Have a good game ! 4d30bca9173f8e0b9cb90e627c422ac5c3a4acf3 647 646 2013-02-13T16:30:11Z Peach 2372 /* Anfangs Aufstellung */ wikitext text/x-wiki == Ziel == Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels. == Regel Zusammenfassung == (Diese Regel Zusammenfassung basiert auf der Spielhilfe von [http://boardgamegeek.com/user/pregremlin Andrew Agard] für Board Game Geek, unter Creative Commons Lizenz. Bitte schauen Sie [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] hier für Details. Vielen Dank Andrew !) ===Anfangs Aufstellung=== * Im Uhrzeigersinn werden werden die Bewohner in freie Felder der Gebäude gesetzt * Fahre gegen den Uhrzeigersinn fort, ausgehend vom letzten Spieler, bis alle Bewohner verteilt sind ===Spielablauf=== ====Phase 0: Reveal the Activity cards==== Reveal activity card for each color corresponding to current round (first 3 rounds only) ====Phase 1: Income and salaries==== Receive 10 deniers and pay 1 per Bishopric and 2 per Palace citizen or lose 2 VP ====Phase 2: Assembling the workforce==== Roll yellow/white/red die per citizen in City Hall/Bishopric/Palace and place in district ====Phase 3: Events==== Reveal top red and white or yellow Event and place to right of queue (unlimited Events) Events take effect from left to right * Military: start player takes 1 black die per die symbol * Other events: see annex (can’t execute: execute as much as possible and lose 2 VP) After Events, roll black dice and counter: * Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once * Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP) * In order players must counter highest remaining until all countered * Use any color dice. Double red dice. Can’t buy dice or use activity cubes ====Phase 4: Actions==== See below. ====Phase 5: End of the round==== Receive deniers from district Return citizens lying on buildings to personal supplies Return unused dice to general supply Pass start player card left. ===Actions=== In order each player can use 1-3 matching dice for one action or pass. Round ends when no dice available or all players have passed May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice ====Activate Activity Card==== Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place citizen on free space (or illustration if full) from personal supply or any board location * 1 tradesman per player per card * Must activate at least once if tradesman hired * Citizens on card cannot be moved to newly freed space Immediate effect: activation cost (round down) determines color and use of dice Delayed effect: place cubes equal to activation cost. Use later (one cube per action) ====Construct Cathedral==== * Use 1-3 white dice to place 1-3 cubes on same-numbered construction site * Must place on lower levels before placing in higher levels for each set of valued spaces * Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6 ====Combat Events==== * Activation cost (round down) defines dice and number of cubes to place on card * Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners Event countered when banners filled * Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards. * 2nd most cubes earns smaller reward (tied: total rounded down) * Most cubes takes card (tied: player who placed first). Discard if neutral has most * Marauding: rewards given, cubes removed, and then event is available again ====Place a citizen on building==== * Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value * Shift existing citizens to right. Citizens pushed off are laid on building illustration * If already have expelled citizen nobody can expel your citizens from that building ====Use Agriculture==== * Gain number of deniers equal to total value divided by 2 (round down) ===Pass=== * If dice still in any city square, pass and receive 2 deniers which are placed in district * Each turn add another denier to district Have a good game ! 364bbde528d234afd19137233e2b874bc0e74508 648 647 2013-02-13T16:41:16Z Peach 2372 /* Spielablauf */ wikitext text/x-wiki == Ziel == Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels. == Regel Zusammenfassung == (Diese Regel Zusammenfassung basiert auf der Spielhilfe von [http://boardgamegeek.com/user/pregremlin Andrew Agard] für Board Game Geek, unter Creative Commons Lizenz. Bitte schauen Sie [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] hier für Details. Vielen Dank Andrew !) ===Anfangs Aufstellung=== * Im Uhrzeigersinn werden werden die Bewohner in freie Felder der Gebäude gesetzt * Fahre gegen den Uhrzeigersinn fort, ausgehend vom letzten Spieler, bis alle Bewohner verteilt sind ===Spielablauf=== ====Phase 0: Aktionskarten aufdecken==== Decke die Aktionskarte für jede Karte entsprechend der aktuellen Runde auf (nur in den ersten 3 Runden) ====Phase 1: Einkommen und Lohn==== Erhalte 10 Deniers und zahle 1 für jeden Bishopric und 2 für jeden Bewohner im Palast oder verliere 2 Siegespunkte ====Phase 2: Aufbau der arbeiterschaft==== Würfle mit gelbem/weißen/roten Würfel für jeden Bewohner im Rathaus/Bishopric/Palast und platziere ihn in deinem Bezirk ====Phase 3: Events==== Decke das oberste rote und weiße oder gelbe Event auf und platziere sie am rechten Ende der Reihe (unbegrenzte Events) Events nehmen Einfluss von links nach rechts * Military: start player takes 1 black die per die symbol * Other events: see annex (can’t execute: execute as much as possible and lose 2 VP) After Events, roll black dice and counter: * Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once * Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP) * In order players must counter highest remaining until all countered * Use any color dice. Double red dice. Can’t buy dice or use activity cubes ====Phase 4: Aktionen==== Siehe unten. ====Phase 5: Ende der Runde==== Nehme Deniers aus deinem Bezirk Return citizens lying on buildings to personal supplies Return unused dice to general supply Gib die Startspieler-Karte nach links ===Actions=== In order each player can use 1-3 matching dice for one action or pass. Round ends when no dice available or all players have passed May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice ====Activate Activity Card==== Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place citizen on free space (or illustration if full) from personal supply or any board location * 1 tradesman per player per card * Must activate at least once if tradesman hired * Citizens on card cannot be moved to newly freed space Immediate effect: activation cost (round down) determines color and use of dice Delayed effect: place cubes equal to activation cost. Use later (one cube per action) ====Construct Cathedral==== * Use 1-3 white dice to place 1-3 cubes on same-numbered construction site * Must place on lower levels before placing in higher levels for each set of valued spaces * Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6 ====Combat Events==== * Activation cost (round down) defines dice and number of cubes to place on card * Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners Event countered when banners filled * Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards. * 2nd most cubes earns smaller reward (tied: total rounded down) * Most cubes takes card (tied: player who placed first). Discard if neutral has most * Marauding: rewards given, cubes removed, and then event is available again ====Place a citizen on building==== * Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value * Shift existing citizens to right. Citizens pushed off are laid on building illustration * If already have expelled citizen nobody can expel your citizens from that building ====Use Agriculture==== * Gain number of deniers equal to total value divided by 2 (round down) ===Pass=== * If dice still in any city square, pass and receive 2 deniers which are placed in district * Each turn add another denier to district Have a good game ! 279f92427ac97dc8d2cf90cb1cb2f33c04c41c42 649 648 2013-02-13T16:43:36Z Peach 2372 /* Aktionen wikitext text/x-wiki == Ziel == Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels. == Regel Zusammenfassung == (Diese Regel Zusammenfassung basiert auf der Spielhilfe von [http://boardgamegeek.com/user/pregremlin Andrew Agard] für Board Game Geek, unter Creative Commons Lizenz. Bitte schauen Sie [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] hier für Details. Vielen Dank Andrew !) ===Anfangs Aufstellung=== * Im Uhrzeigersinn werden werden die Bewohner in freie Felder der Gebäude gesetzt * Fahre gegen den Uhrzeigersinn fort, ausgehend vom letzten Spieler, bis alle Bewohner verteilt sind ===Spielablauf=== ====Phase 0: Aktionskarten aufdecken==== Decke die Aktionskarte für jede Karte entsprechend der aktuellen Runde auf (nur in den ersten 3 Runden) ====Phase 1: Einkommen und Lohn==== Erhalte 10 Deniers und zahle 1 für jeden Bishopric und 2 für jeden Bewohner im Palast oder verliere 2 Siegespunkte ====Phase 2: Aufbau der arbeiterschaft==== Würfle mit gelbem/weißen/roten Würfel für jeden Bewohner im Rathaus/Bishopric/Palast und platziere ihn in deinem Bezirk ====Phase 3: Events==== Decke das oberste rote und weiße oder gelbe Event auf und platziere sie am rechten Ende der Reihe (unbegrenzte Events) Events nehmen Einfluss von links nach rechts * Military: start player takes 1 black die per die symbol * Other events: see annex (can’t execute: execute as much as possible and lose 2 VP) After Events, roll black dice and counter: * Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once * Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP) * In order players must counter highest remaining until all countered * Use any color dice. Double red dice. Can’t buy dice or use activity cubes ====Phase 4: Aktionen==== Siehe unten. ====Phase 5: Ende der Runde==== Nehme Deniers aus deinem Bezirk Return citizens lying on buildings to personal supplies Return unused dice to general supply Gib die Startspieler-Karte nach links ===Aktionen=== In order each player can use 1-3 matching dice for one action or pass. Round ends when no dice available or all players have passed May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice ====Aktionskarten aktivieren==== Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place citizen on free space (or illustration if full) from personal supply or any board location * 1 tradesman per player per card * Must activate at least once if tradesman hired * Citizens on card cannot be moved to newly freed space Immediate effect: activation cost (round down) determines color and use of dice Delayed effect: place cubes equal to activation cost. Use later (one cube per action) ====Construct Cathedral==== * Use 1-3 white dice to place 1-3 cubes on same-numbered construction site * Must place on lower levels before placing in higher levels for each set of valued spaces * Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6 ====Kampf Events==== * Activation cost (round down) defines dice and number of cubes to place on card * Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners Event countered when banners filled * Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards. * 2nd most cubes earns smaller reward (tied: total rounded down) * Most cubes takes card (tied: player who placed first). Discard if neutral has most * Marauding: rewards given, cubes removed, and then event is available again ====Platzieren einen Bewohner in einem Gebäude==== * Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value * Shift existing citizens to right. Citizens pushed off are laid on building illustration * If already have expelled citizen nobody can expel your citizens from that building ====Benutze Landwirtschaft==== * Erhalte eine Anzahl an Deniers gleich der Summe der Würfel durch 2 (abgerundet) ===Pass=== * If dice still in any city square, pass and receive 2 deniers which are placed in district * Each turn add another denier to district Have a good game ! a98c831f0b41c9f17c1b958e8162765515b1e1ce Deck 0 101 650 641 2013-02-13T17:02:33Z Sourisdudesert 1 wikitext text/x-wiki "Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side. Using "deck", you will be able to use the following features without writing a single SQL database request: * Place cards in pile, shuffle cards, draw cards one by one or many by many. * "Auto-reshuffle" discard pile into deck when deck is empty. * Move cards between different locations: hands of players, the table, ... == Using Deck: Hearts example == Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times. == Deck overview == With Deck component, you manage all cards of your game. === The 5 properties of each card === Using Deck component, each card will have 5 properties: * '''id''': This is the unique ID of each card. * '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?). * '''location''' and '''location_arg''': These two values defines where is the card at now. id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area. '''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game. '''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below. Examples of usage of "type" and "type_arg": * In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K). * In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used. * In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile. '''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer. You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs: * 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn). * 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player. * 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle"). Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game. === Create a new Deck component === For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql": <pre> CREATE TABLE IF NOT EXISTS `card` ( `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `card_type` varchar(16) NOT NULL, `card_type_arg` int(11) NOT NULL, `card_location` varchar(16) NOT NULL, `card_location_arg` int(11) NOT NULL, PRIMARY KEY (`card_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method: <pre> $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); </pre> Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game). Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method. "Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts": <pre> // Create cards $cards = array(); foreach( $this->colors as $color_id => $color ) // spade, heart, diamond, club { for( $value=2; $value<=14; $value++ ) // 2, 3, 4, ... K, A { $cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1); } } $this->cards->createCards( $cards, 'deck' ); </pre> As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument). Now, you are ready to use "Deck"! === Simple examples using Deck === (Most examples are from "Hearts" game) <pre> // In "getAllDatas', we need to send to the current player all the cards he has in hand: $result['hand'] = $this->cards->getCardsInLocation( 'hand', $player_id ); </pre> <pre> // At some time we want to check if all the cards (52) are in player's hands: if( $this->cards->countCardInLocation( 'hand' ) == 52 ) // do something </pre> <pre> // When a player plays a card in front of him on the table: $this->cards->moveCard( $card_id, 'cardsontable', $player_id ); // Note the use of the custom location 'cardsontable' here to keep track of cards on the table. </pre> <pre> // This is a new hand: let's gather all cards from everywhere in the deck: $this->cards->moveAllCardsInLocation( null, "deck" ); // And then shuffle the deck $this->cards->shuffle( 'deck' ); // And then deal 13 cards to each player // Deal 13 cards to each players // Create deck, shuffle it and give 13 initial cards $players = self::loadPlayersBasicInfos(); foreach( $players as $player_id => $player ) { $cards = $this->cards->pickCards( 13, 'deck', $player_id ); // Notify player about his cards self::notifyPlayer( $player_id, 'newHand', '', array( 'cards' => $cards ) ); } // Note the use of "notifyPlayer" instead of "notifyAllPlayers": new cards is a private information ;) </pre> == Deck component reference == === Initializing Deck component === '''init( $table_name )''' Initialize the Deck component. Argument: * table_name: name of the DB table used by this Deck component. Must be called before any other Deck method. Usually, init is called in your game constructor. Example with Hearts: <pre> function Hearts( ) { (...) $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); } </pre> '''createCards( $cards, $location='deck', $location_arg=null )''' Create card items in your deck component. Usually, all card items are created once, during the setup phase of the game. "cards" describe all cards that need to be created. "cards" is an array with the following format: <pre> // Create 1 card of type "1" with type_arg=99, // and 4 cards of type "2" with type_arg=12, // and 2 cards of type "3" with type_arg=33 $cards = array( array( 'type' => 1, 'type_arg' => 99, nbr' => 1 ), array( 'type' => 2, 'type_arg' => 12, nbr' => 4 ), array( 'type' => 3, 'type_arg' => 33, nbr' => 2 ) ... ); </pre> Note: During the "createCards" process, Deck generate unique IDs for all card items. Note: createCards is optimized to create a lot of cards at once. Do not use it to create cards one by one. If "location" and "location_arg" arguments are not set, newly created cards are placed in the "deck" location. If "location" (and optionally location_arg) is specified, cards are created for this specific location. === Card standard format === When Deck component methods are returning one or several cards, the following format is used: <pre> array( 'id' => .., // the card ID 'type' => .., // the card type 'type_arg' => .., // the card type argument 'location' => .., // the card location 'location_arg' => .. // the card location argument ); <pre> === Picking cards === '''pickCard( $location, $player_id )''' Pick a card from a "pile" location (ex: "deck") and place it in the "hand" of specified player. Return the card picked or "null" if there are no more card in given location. This method supports auto-reshuffle (see "auto-reshuffle" below). '''pickCards( $nbr, $location, $player_id )''' Pick "$nbr" cards from a "pile" location (ex: "deck") and place them in the "hand" of specified player. Return an array with the cards picked, or "null" if there are no more card in given location. Note that the number of cards picked can be less than "$nbr" in case there are not enough cards in the pile location. This method supports auto-reshuffle (see "auto-reshuffle" below). In case there are not enough cards in the pile, all remaining cards are picked first, then the auto-reshuffle is triggered, then the other cards are picked. '''pickCardForLocation( $from_location, $to_location, $location_arg=0 )''' This method is similar to 'pickCard', except that you can pick a card for any sort of location and not only the "hand" location. _ from_location is the "pile" style location from where you are picking a card. _ to_location is the location where you will place the card picked. _ if "location_arg" is specified, the card picked will be set with this "location_arg". This method supports auto-reshuffle (see "auto-reshuffle" below). '''pickCardsForLocation( $nbr, $from_location, $to_location, $location_arg=0, $no_deck_reform=false )''' This method is similar to 'pickCards', except that you can pick cards for any sort of location and not only the "hand" location. _ from_location is the "pile" style location from where you are picking some cards. _ to_location is the location where you will place the cards picked. _ if "location_arg" is specified, the cards picked will be set with this "location_arg". _ if "no_deck_reform" is set to "true", the auto-reshuffle feature is disabled during this method call. This method supports auto-reshuffle (see "auto-reshuffle" below). === Moving cards === '''moveCard( $card_id, $location, $location_arg=0 )''' Move the specific card to given location. _ card_id: ID of the card to move. _ location: location where to move the card. _ location_arg: if specified, location_arg where to move the card. If not specified "location_arg" will be set to 0. '''moveCards( $cards, $location, $location_arg )''' Move the specific cards to given location. _ cards: an array of IDs of cards to move. _ location: location where to move the cards. _ location_arg: if specified, location_arg where to move the cards. If not specified "location_arg" will be set to 0. '''insertCard( $card_id, $location, $location_arg )''' Move a card to a specific "pile" location where card are ordered. If location_arg place is already taken, increment all cards after location_arg in order to insert new card at this precise location. (note: insertCardOnExtremePosition method below is more useful in most of the case) '''insertCardOnExtremePosition( $card_id, $location, $bOnTop )''' Move a card on top or at bottom of given "pile" type location. '''moveAllCardsInLocation( $from_location, $to_location, $from_location_arg=null, $to_location_arg=0 )''' Move all cards in specified "from" location to given location. _ from_location: where to take the cards _ to_location: where to put the cards _ from_location (optional): if specified, only cards with given "location_arg" are moved. _ to_location (optional): if specified, cards moved "location_arg" is set to given value. Otherwise location_arg is set to zero. Note: if you want to keep "location_arg" untouched, you should use "moveAllCardsInLocationKeepOrder" below. '''moveAllCardsInLocationKeepOrder( $from_location, $to_location )''' Move all cards in specified "from" location to given "to" location. This method does not modify the "location_arg" of cards. '''playCard( $card_id )''' Move specified card at the top of the "discard" location. Note: this is an alias for: insertCardOnExtremePosition( $card_id, "discard", true ) === Get cards informations === '''getCard( $card_id )''' Get specific card information. Return null if this card is not found. '''getCards( $cards_array )''' Get specific cards information. cards_array is an array of cards ID. If some cards are not found or if some cards IDs are specified multiple times, the method throws an (unexpected) Exception. '''getCardsInLocation( $location, $location_arg = null, $order_by = null )''' Get all cards in specific location, as an array. Return an empty array if the location is empty. _ location (string): the location where to get the cards. _ location_arg (optional): if specified, return only cards with the specified "location_arg". _ order_by (optional): if specified, returned cards are ordered by the given database field. Example: "card_id" or "card_type". '''countCardInLocation( $location, $location_arg=null )''' Return the number of cards in specified location. _ location (string): the location where to count the cards. _ location_arg (optional): if specified, count only cards with the specified "location_arg". '''countCardsInLocations()''' Return the number of cards in each location of the game. The method returns an associative array with the format "location" => "number of cards". Example: <pre> array( 'deck' => 12, 'hand' => 21, 'discard' => 54, 'ontable' => 3 ); </pre> '''countCardsByLocationArgs( $location )''' Return the number of cards in each "location_arg" for the given location. The method returns an associative array with the format "location_arg" => "number of cards". Example: count the number of cards in each player's hand: <pre> countCardsByLocationArgs( 'hand' ); // Result: array( 122345 => 5, // player 122345 has 5 cards in hand 123456 => 4 // and player 123456 has 4 cards in hand ); </pre> '''getPlayerHand( $player_id )''' Get all cards in given player hand. Note: This is an alias for: getCardsInLocation( "hand", $player_id ) '''getCardOnTop( $location )''' Get the card on top of the given ("pile" style) location, or null if the location is empty. Note that the card pile won't be "auto-reshuffled" if there is no more card available. '''getCardsOnTop( $nbr, $location )''' Get the "$nbr" cards on top of the given ("pile" style) location. The method return an array with at most "$nbr" elements (or a void array if there is no card in this location). Note that the card pile won't be "auto-reshuffled" if there is not enough cards available. '''getExtremePosition( $bGetMax ,$location )''' (rarely used) Get the position of cards at the top of the given location / at the bottom of the given location. Of course this method works only on location in "pile" where you are using "location_arg" to specify the position of each card (example: "deck" location). If bGetMax=true, return the location of the top card of the pile. If bGetMax=false, return the location of the bottom card of the pile. '''getCardsOfType( $type, $type_arg=null )''' Get all cards of a specific type (rarely used). Return an array of cards, or an empty array if there is no cards of the specified type. _ type: the type of cards _ type_arg: if specified, return only cards with the specified "type_arg". === Shuffling === '''shuffle( $location )''' Shuffle all cards in specific location. Shuffle only works on locations where cards are on a "pile" (ex: "deck"). Please note that all "location_arg" will be reseted to reflect the new order of the cards in the pile. 97f690a53ba2e3134edbadeca0c00a07ceff10e2 651 650 2013-02-13T17:03:05Z Sourisdudesert 1 /* Card standard format */ wikitext text/x-wiki "Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side. Using "deck", you will be able to use the following features without writing a single SQL database request: * Place cards in pile, shuffle cards, draw cards one by one or many by many. * "Auto-reshuffle" discard pile into deck when deck is empty. * Move cards between different locations: hands of players, the table, ... == Using Deck: Hearts example == Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times. == Deck overview == With Deck component, you manage all cards of your game. === The 5 properties of each card === Using Deck component, each card will have 5 properties: * '''id''': This is the unique ID of each card. * '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?). * '''location''' and '''location_arg''': These two values defines where is the card at now. id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area. '''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game. '''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below. Examples of usage of "type" and "type_arg": * In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K). * In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used. * In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile. '''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer. You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs: * 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn). * 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player. * 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle"). Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game. === Create a new Deck component === For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql": <pre> CREATE TABLE IF NOT EXISTS `card` ( `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `card_type` varchar(16) NOT NULL, `card_type_arg` int(11) NOT NULL, `card_location` varchar(16) NOT NULL, `card_location_arg` int(11) NOT NULL, PRIMARY KEY (`card_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method: <pre> $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); </pre> Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game). Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method. "Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts": <pre> // Create cards $cards = array(); foreach( $this->colors as $color_id => $color ) // spade, heart, diamond, club { for( $value=2; $value<=14; $value++ ) // 2, 3, 4, ... K, A { $cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1); } } $this->cards->createCards( $cards, 'deck' ); </pre> As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument). Now, you are ready to use "Deck"! === Simple examples using Deck === (Most examples are from "Hearts" game) <pre> // In "getAllDatas', we need to send to the current player all the cards he has in hand: $result['hand'] = $this->cards->getCardsInLocation( 'hand', $player_id ); </pre> <pre> // At some time we want to check if all the cards (52) are in player's hands: if( $this->cards->countCardInLocation( 'hand' ) == 52 ) // do something </pre> <pre> // When a player plays a card in front of him on the table: $this->cards->moveCard( $card_id, 'cardsontable', $player_id ); // Note the use of the custom location 'cardsontable' here to keep track of cards on the table. </pre> <pre> // This is a new hand: let's gather all cards from everywhere in the deck: $this->cards->moveAllCardsInLocation( null, "deck" ); // And then shuffle the deck $this->cards->shuffle( 'deck' ); // And then deal 13 cards to each player // Deal 13 cards to each players // Create deck, shuffle it and give 13 initial cards $players = self::loadPlayersBasicInfos(); foreach( $players as $player_id => $player ) { $cards = $this->cards->pickCards( 13, 'deck', $player_id ); // Notify player about his cards self::notifyPlayer( $player_id, 'newHand', '', array( 'cards' => $cards ) ); } // Note the use of "notifyPlayer" instead of "notifyAllPlayers": new cards is a private information ;) </pre> == Deck component reference == === Initializing Deck component === '''init( $table_name )''' Initialize the Deck component. Argument: * table_name: name of the DB table used by this Deck component. Must be called before any other Deck method. Usually, init is called in your game constructor. Example with Hearts: <pre> function Hearts( ) { (...) $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); } </pre> '''createCards( $cards, $location='deck', $location_arg=null )''' Create card items in your deck component. Usually, all card items are created once, during the setup phase of the game. "cards" describe all cards that need to be created. "cards" is an array with the following format: <pre> // Create 1 card of type "1" with type_arg=99, // and 4 cards of type "2" with type_arg=12, // and 2 cards of type "3" with type_arg=33 $cards = array( array( 'type' => 1, 'type_arg' => 99, nbr' => 1 ), array( 'type' => 2, 'type_arg' => 12, nbr' => 4 ), array( 'type' => 3, 'type_arg' => 33, nbr' => 2 ) ... ); </pre> Note: During the "createCards" process, Deck generate unique IDs for all card items. Note: createCards is optimized to create a lot of cards at once. Do not use it to create cards one by one. If "location" and "location_arg" arguments are not set, newly created cards are placed in the "deck" location. If "location" (and optionally location_arg) is specified, cards are created for this specific location. === Card standard format === When Deck component methods are returning one or several cards, the following format is used: <pre> array( 'id' => .., // the card ID 'type' => .., // the card type 'type_arg' => .., // the card type argument 'location' => .., // the card location 'location_arg' => .. // the card location argument ); </pre> === Picking cards === '''pickCard( $location, $player_id )''' Pick a card from a "pile" location (ex: "deck") and place it in the "hand" of specified player. Return the card picked or "null" if there are no more card in given location. This method supports auto-reshuffle (see "auto-reshuffle" below). '''pickCards( $nbr, $location, $player_id )''' Pick "$nbr" cards from a "pile" location (ex: "deck") and place them in the "hand" of specified player. Return an array with the cards picked, or "null" if there are no more card in given location. Note that the number of cards picked can be less than "$nbr" in case there are not enough cards in the pile location. This method supports auto-reshuffle (see "auto-reshuffle" below). In case there are not enough cards in the pile, all remaining cards are picked first, then the auto-reshuffle is triggered, then the other cards are picked. '''pickCardForLocation( $from_location, $to_location, $location_arg=0 )''' This method is similar to 'pickCard', except that you can pick a card for any sort of location and not only the "hand" location. _ from_location is the "pile" style location from where you are picking a card. _ to_location is the location where you will place the card picked. _ if "location_arg" is specified, the card picked will be set with this "location_arg". This method supports auto-reshuffle (see "auto-reshuffle" below). '''pickCardsForLocation( $nbr, $from_location, $to_location, $location_arg=0, $no_deck_reform=false )''' This method is similar to 'pickCards', except that you can pick cards for any sort of location and not only the "hand" location. _ from_location is the "pile" style location from where you are picking some cards. _ to_location is the location where you will place the cards picked. _ if "location_arg" is specified, the cards picked will be set with this "location_arg". _ if "no_deck_reform" is set to "true", the auto-reshuffle feature is disabled during this method call. This method supports auto-reshuffle (see "auto-reshuffle" below). === Moving cards === '''moveCard( $card_id, $location, $location_arg=0 )''' Move the specific card to given location. _ card_id: ID of the card to move. _ location: location where to move the card. _ location_arg: if specified, location_arg where to move the card. If not specified "location_arg" will be set to 0. '''moveCards( $cards, $location, $location_arg )''' Move the specific cards to given location. _ cards: an array of IDs of cards to move. _ location: location where to move the cards. _ location_arg: if specified, location_arg where to move the cards. If not specified "location_arg" will be set to 0. '''insertCard( $card_id, $location, $location_arg )''' Move a card to a specific "pile" location where card are ordered. If location_arg place is already taken, increment all cards after location_arg in order to insert new card at this precise location. (note: insertCardOnExtremePosition method below is more useful in most of the case) '''insertCardOnExtremePosition( $card_id, $location, $bOnTop )''' Move a card on top or at bottom of given "pile" type location. '''moveAllCardsInLocation( $from_location, $to_location, $from_location_arg=null, $to_location_arg=0 )''' Move all cards in specified "from" location to given location. _ from_location: where to take the cards _ to_location: where to put the cards _ from_location (optional): if specified, only cards with given "location_arg" are moved. _ to_location (optional): if specified, cards moved "location_arg" is set to given value. Otherwise location_arg is set to zero. Note: if you want to keep "location_arg" untouched, you should use "moveAllCardsInLocationKeepOrder" below. '''moveAllCardsInLocationKeepOrder( $from_location, $to_location )''' Move all cards in specified "from" location to given "to" location. This method does not modify the "location_arg" of cards. '''playCard( $card_id )''' Move specified card at the top of the "discard" location. Note: this is an alias for: insertCardOnExtremePosition( $card_id, "discard", true ) === Get cards informations === '''getCard( $card_id )''' Get specific card information. Return null if this card is not found. '''getCards( $cards_array )''' Get specific cards information. cards_array is an array of cards ID. If some cards are not found or if some cards IDs are specified multiple times, the method throws an (unexpected) Exception. '''getCardsInLocation( $location, $location_arg = null, $order_by = null )''' Get all cards in specific location, as an array. Return an empty array if the location is empty. _ location (string): the location where to get the cards. _ location_arg (optional): if specified, return only cards with the specified "location_arg". _ order_by (optional): if specified, returned cards are ordered by the given database field. Example: "card_id" or "card_type". '''countCardInLocation( $location, $location_arg=null )''' Return the number of cards in specified location. _ location (string): the location where to count the cards. _ location_arg (optional): if specified, count only cards with the specified "location_arg". '''countCardsInLocations()''' Return the number of cards in each location of the game. The method returns an associative array with the format "location" => "number of cards". Example: <pre> array( 'deck' => 12, 'hand' => 21, 'discard' => 54, 'ontable' => 3 ); </pre> '''countCardsByLocationArgs( $location )''' Return the number of cards in each "location_arg" for the given location. The method returns an associative array with the format "location_arg" => "number of cards". Example: count the number of cards in each player's hand: <pre> countCardsByLocationArgs( 'hand' ); // Result: array( 122345 => 5, // player 122345 has 5 cards in hand 123456 => 4 // and player 123456 has 4 cards in hand ); </pre> '''getPlayerHand( $player_id )''' Get all cards in given player hand. Note: This is an alias for: getCardsInLocation( "hand", $player_id ) '''getCardOnTop( $location )''' Get the card on top of the given ("pile" style) location, or null if the location is empty. Note that the card pile won't be "auto-reshuffled" if there is no more card available. '''getCardsOnTop( $nbr, $location )''' Get the "$nbr" cards on top of the given ("pile" style) location. The method return an array with at most "$nbr" elements (or a void array if there is no card in this location). Note that the card pile won't be "auto-reshuffled" if there is not enough cards available. '''getExtremePosition( $bGetMax ,$location )''' (rarely used) Get the position of cards at the top of the given location / at the bottom of the given location. Of course this method works only on location in "pile" where you are using "location_arg" to specify the position of each card (example: "deck" location). If bGetMax=true, return the location of the top card of the pile. If bGetMax=false, return the location of the bottom card of the pile. '''getCardsOfType( $type, $type_arg=null )''' Get all cards of a specific type (rarely used). Return an array of cards, or an empty array if there is no cards of the specified type. _ type: the type of cards _ type_arg: if specified, return only cards with the specified "type_arg". === Shuffling === '''shuffle( $location )''' Shuffle all cards in specific location. Shuffle only works on locations where cards are on a "pile" (ex: "deck"). Please note that all "location_arg" will be reseted to reflect the new order of the cards in the pile. 30cc7f35ff1f13c94e1d1122b1dafc9e8a0dd77c 652 651 2013-02-13T17:03:29Z Sourisdudesert 1 /* Picking cards */ wikitext text/x-wiki "Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side. Using "deck", you will be able to use the following features without writing a single SQL database request: * Place cards in pile, shuffle cards, draw cards one by one or many by many. * "Auto-reshuffle" discard pile into deck when deck is empty. * Move cards between different locations: hands of players, the table, ... == Using Deck: Hearts example == Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times. == Deck overview == With Deck component, you manage all cards of your game. === The 5 properties of each card === Using Deck component, each card will have 5 properties: * '''id''': This is the unique ID of each card. * '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?). * '''location''' and '''location_arg''': These two values defines where is the card at now. id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area. '''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game. '''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below. Examples of usage of "type" and "type_arg": * In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K). * In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used. * In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile. '''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer. You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs: * 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn). * 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player. * 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle"). Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game. === Create a new Deck component === For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql": <pre> CREATE TABLE IF NOT EXISTS `card` ( `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `card_type` varchar(16) NOT NULL, `card_type_arg` int(11) NOT NULL, `card_location` varchar(16) NOT NULL, `card_location_arg` int(11) NOT NULL, PRIMARY KEY (`card_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method: <pre> $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); </pre> Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game). Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method. "Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts": <pre> // Create cards $cards = array(); foreach( $this->colors as $color_id => $color ) // spade, heart, diamond, club { for( $value=2; $value<=14; $value++ ) // 2, 3, 4, ... K, A { $cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1); } } $this->cards->createCards( $cards, 'deck' ); </pre> As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument). Now, you are ready to use "Deck"! === Simple examples using Deck === (Most examples are from "Hearts" game) <pre> // In "getAllDatas', we need to send to the current player all the cards he has in hand: $result['hand'] = $this->cards->getCardsInLocation( 'hand', $player_id ); </pre> <pre> // At some time we want to check if all the cards (52) are in player's hands: if( $this->cards->countCardInLocation( 'hand' ) == 52 ) // do something </pre> <pre> // When a player plays a card in front of him on the table: $this->cards->moveCard( $card_id, 'cardsontable', $player_id ); // Note the use of the custom location 'cardsontable' here to keep track of cards on the table. </pre> <pre> // This is a new hand: let's gather all cards from everywhere in the deck: $this->cards->moveAllCardsInLocation( null, "deck" ); // And then shuffle the deck $this->cards->shuffle( 'deck' ); // And then deal 13 cards to each player // Deal 13 cards to each players // Create deck, shuffle it and give 13 initial cards $players = self::loadPlayersBasicInfos(); foreach( $players as $player_id => $player ) { $cards = $this->cards->pickCards( 13, 'deck', $player_id ); // Notify player about his cards self::notifyPlayer( $player_id, 'newHand', '', array( 'cards' => $cards ) ); } // Note the use of "notifyPlayer" instead of "notifyAllPlayers": new cards is a private information ;) </pre> == Deck component reference == === Initializing Deck component === '''init( $table_name )''' Initialize the Deck component. Argument: * table_name: name of the DB table used by this Deck component. Must be called before any other Deck method. Usually, init is called in your game constructor. Example with Hearts: <pre> function Hearts( ) { (...) $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); } </pre> '''createCards( $cards, $location='deck', $location_arg=null )''' Create card items in your deck component. Usually, all card items are created once, during the setup phase of the game. "cards" describe all cards that need to be created. "cards" is an array with the following format: <pre> // Create 1 card of type "1" with type_arg=99, // and 4 cards of type "2" with type_arg=12, // and 2 cards of type "3" with type_arg=33 $cards = array( array( 'type' => 1, 'type_arg' => 99, nbr' => 1 ), array( 'type' => 2, 'type_arg' => 12, nbr' => 4 ), array( 'type' => 3, 'type_arg' => 33, nbr' => 2 ) ... ); </pre> Note: During the "createCards" process, Deck generate unique IDs for all card items. Note: createCards is optimized to create a lot of cards at once. Do not use it to create cards one by one. If "location" and "location_arg" arguments are not set, newly created cards are placed in the "deck" location. If "location" (and optionally location_arg) is specified, cards are created for this specific location. === Card standard format === When Deck component methods are returning one or several cards, the following format is used: <pre> array( 'id' => .., // the card ID 'type' => .., // the card type 'type_arg' => .., // the card type argument 'location' => .., // the card location 'location_arg' => .. // the card location argument ); </pre> === Picking cards === '''pickCard( $location, $player_id )''' Pick a card from a "pile" location (ex: "deck") and place it in the "hand" of specified player. Return the card picked or "null" if there are no more card in given location. This method supports auto-reshuffle (see "auto-reshuffle" below). '''pickCards( $nbr, $location, $player_id )''' Pick "$nbr" cards from a "pile" location (ex: "deck") and place them in the "hand" of specified player. Return an array with the cards picked, or "null" if there are no more card in given location. Note that the number of cards picked can be less than "$nbr" in case there are not enough cards in the pile location. This method supports auto-reshuffle (see "auto-reshuffle" below). In case there are not enough cards in the pile, all remaining cards are picked first, then the auto-reshuffle is triggered, then the other cards are picked. '''pickCardForLocation( $from_location, $to_location, $location_arg=0 )''' This method is similar to 'pickCard', except that you can pick a card for any sort of location and not only the "hand" location. * from_location is the "pile" style location from where you are picking a card. * to_location is the location where you will place the card picked. * if "location_arg" is specified, the card picked will be set with this "location_arg". This method supports auto-reshuffle (see "auto-reshuffle" below). '''pickCardsForLocation( $nbr, $from_location, $to_location, $location_arg=0, $no_deck_reform=false )''' This method is similar to 'pickCards', except that you can pick cards for any sort of location and not only the "hand" location. * from_location is the "pile" style location from where you are picking some cards. * to_location is the location where you will place the cards picked. * if "location_arg" is specified, the cards picked will be set with this "location_arg". * if "no_deck_reform" is set to "true", the auto-reshuffle feature is disabled during this method call. This method supports auto-reshuffle (see "auto-reshuffle" below). === Moving cards === '''moveCard( $card_id, $location, $location_arg=0 )''' Move the specific card to given location. _ card_id: ID of the card to move. _ location: location where to move the card. _ location_arg: if specified, location_arg where to move the card. If not specified "location_arg" will be set to 0. '''moveCards( $cards, $location, $location_arg )''' Move the specific cards to given location. _ cards: an array of IDs of cards to move. _ location: location where to move the cards. _ location_arg: if specified, location_arg where to move the cards. If not specified "location_arg" will be set to 0. '''insertCard( $card_id, $location, $location_arg )''' Move a card to a specific "pile" location where card are ordered. If location_arg place is already taken, increment all cards after location_arg in order to insert new card at this precise location. (note: insertCardOnExtremePosition method below is more useful in most of the case) '''insertCardOnExtremePosition( $card_id, $location, $bOnTop )''' Move a card on top or at bottom of given "pile" type location. '''moveAllCardsInLocation( $from_location, $to_location, $from_location_arg=null, $to_location_arg=0 )''' Move all cards in specified "from" location to given location. _ from_location: where to take the cards _ to_location: where to put the cards _ from_location (optional): if specified, only cards with given "location_arg" are moved. _ to_location (optional): if specified, cards moved "location_arg" is set to given value. Otherwise location_arg is set to zero. Note: if you want to keep "location_arg" untouched, you should use "moveAllCardsInLocationKeepOrder" below. '''moveAllCardsInLocationKeepOrder( $from_location, $to_location )''' Move all cards in specified "from" location to given "to" location. This method does not modify the "location_arg" of cards. '''playCard( $card_id )''' Move specified card at the top of the "discard" location. Note: this is an alias for: insertCardOnExtremePosition( $card_id, "discard", true ) === Get cards informations === '''getCard( $card_id )''' Get specific card information. Return null if this card is not found. '''getCards( $cards_array )''' Get specific cards information. cards_array is an array of cards ID. If some cards are not found or if some cards IDs are specified multiple times, the method throws an (unexpected) Exception. '''getCardsInLocation( $location, $location_arg = null, $order_by = null )''' Get all cards in specific location, as an array. Return an empty array if the location is empty. _ location (string): the location where to get the cards. _ location_arg (optional): if specified, return only cards with the specified "location_arg". _ order_by (optional): if specified, returned cards are ordered by the given database field. Example: "card_id" or "card_type". '''countCardInLocation( $location, $location_arg=null )''' Return the number of cards in specified location. _ location (string): the location where to count the cards. _ location_arg (optional): if specified, count only cards with the specified "location_arg". '''countCardsInLocations()''' Return the number of cards in each location of the game. The method returns an associative array with the format "location" => "number of cards". Example: <pre> array( 'deck' => 12, 'hand' => 21, 'discard' => 54, 'ontable' => 3 ); </pre> '''countCardsByLocationArgs( $location )''' Return the number of cards in each "location_arg" for the given location. The method returns an associative array with the format "location_arg" => "number of cards". Example: count the number of cards in each player's hand: <pre> countCardsByLocationArgs( 'hand' ); // Result: array( 122345 => 5, // player 122345 has 5 cards in hand 123456 => 4 // and player 123456 has 4 cards in hand ); </pre> '''getPlayerHand( $player_id )''' Get all cards in given player hand. Note: This is an alias for: getCardsInLocation( "hand", $player_id ) '''getCardOnTop( $location )''' Get the card on top of the given ("pile" style) location, or null if the location is empty. Note that the card pile won't be "auto-reshuffled" if there is no more card available. '''getCardsOnTop( $nbr, $location )''' Get the "$nbr" cards on top of the given ("pile" style) location. The method return an array with at most "$nbr" elements (or a void array if there is no card in this location). Note that the card pile won't be "auto-reshuffled" if there is not enough cards available. '''getExtremePosition( $bGetMax ,$location )''' (rarely used) Get the position of cards at the top of the given location / at the bottom of the given location. Of course this method works only on location in "pile" where you are using "location_arg" to specify the position of each card (example: "deck" location). If bGetMax=true, return the location of the top card of the pile. If bGetMax=false, return the location of the bottom card of the pile. '''getCardsOfType( $type, $type_arg=null )''' Get all cards of a specific type (rarely used). Return an array of cards, or an empty array if there is no cards of the specified type. _ type: the type of cards _ type_arg: if specified, return only cards with the specified "type_arg". === Shuffling === '''shuffle( $location )''' Shuffle all cards in specific location. Shuffle only works on locations where cards are on a "pile" (ex: "deck"). Please note that all "location_arg" will be reseted to reflect the new order of the cards in the pile. a290d4ecd4c4c4fee059d59ff4808671f7971637 653 652 2013-02-13T17:03:50Z Sourisdudesert 1 /* Moving cards */ wikitext text/x-wiki "Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side. Using "deck", you will be able to use the following features without writing a single SQL database request: * Place cards in pile, shuffle cards, draw cards one by one or many by many. * "Auto-reshuffle" discard pile into deck when deck is empty. * Move cards between different locations: hands of players, the table, ... == Using Deck: Hearts example == Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times. == Deck overview == With Deck component, you manage all cards of your game. === The 5 properties of each card === Using Deck component, each card will have 5 properties: * '''id''': This is the unique ID of each card. * '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?). * '''location''' and '''location_arg''': These two values defines where is the card at now. id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area. '''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game. '''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below. Examples of usage of "type" and "type_arg": * In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K). * In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used. * In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile. '''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer. You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs: * 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn). * 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player. * 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle"). Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game. === Create a new Deck component === For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql": <pre> CREATE TABLE IF NOT EXISTS `card` ( `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `card_type` varchar(16) NOT NULL, `card_type_arg` int(11) NOT NULL, `card_location` varchar(16) NOT NULL, `card_location_arg` int(11) NOT NULL, PRIMARY KEY (`card_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method: <pre> $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); </pre> Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game). Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method. "Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts": <pre> // Create cards $cards = array(); foreach( $this->colors as $color_id => $color ) // spade, heart, diamond, club { for( $value=2; $value<=14; $value++ ) // 2, 3, 4, ... K, A { $cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1); } } $this->cards->createCards( $cards, 'deck' ); </pre> As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument). Now, you are ready to use "Deck"! === Simple examples using Deck === (Most examples are from "Hearts" game) <pre> // In "getAllDatas', we need to send to the current player all the cards he has in hand: $result['hand'] = $this->cards->getCardsInLocation( 'hand', $player_id ); </pre> <pre> // At some time we want to check if all the cards (52) are in player's hands: if( $this->cards->countCardInLocation( 'hand' ) == 52 ) // do something </pre> <pre> // When a player plays a card in front of him on the table: $this->cards->moveCard( $card_id, 'cardsontable', $player_id ); // Note the use of the custom location 'cardsontable' here to keep track of cards on the table. </pre> <pre> // This is a new hand: let's gather all cards from everywhere in the deck: $this->cards->moveAllCardsInLocation( null, "deck" ); // And then shuffle the deck $this->cards->shuffle( 'deck' ); // And then deal 13 cards to each player // Deal 13 cards to each players // Create deck, shuffle it and give 13 initial cards $players = self::loadPlayersBasicInfos(); foreach( $players as $player_id => $player ) { $cards = $this->cards->pickCards( 13, 'deck', $player_id ); // Notify player about his cards self::notifyPlayer( $player_id, 'newHand', '', array( 'cards' => $cards ) ); } // Note the use of "notifyPlayer" instead of "notifyAllPlayers": new cards is a private information ;) </pre> == Deck component reference == === Initializing Deck component === '''init( $table_name )''' Initialize the Deck component. Argument: * table_name: name of the DB table used by this Deck component. Must be called before any other Deck method. Usually, init is called in your game constructor. Example with Hearts: <pre> function Hearts( ) { (...) $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); } </pre> '''createCards( $cards, $location='deck', $location_arg=null )''' Create card items in your deck component. Usually, all card items are created once, during the setup phase of the game. "cards" describe all cards that need to be created. "cards" is an array with the following format: <pre> // Create 1 card of type "1" with type_arg=99, // and 4 cards of type "2" with type_arg=12, // and 2 cards of type "3" with type_arg=33 $cards = array( array( 'type' => 1, 'type_arg' => 99, nbr' => 1 ), array( 'type' => 2, 'type_arg' => 12, nbr' => 4 ), array( 'type' => 3, 'type_arg' => 33, nbr' => 2 ) ... ); </pre> Note: During the "createCards" process, Deck generate unique IDs for all card items. Note: createCards is optimized to create a lot of cards at once. Do not use it to create cards one by one. If "location" and "location_arg" arguments are not set, newly created cards are placed in the "deck" location. If "location" (and optionally location_arg) is specified, cards are created for this specific location. === Card standard format === When Deck component methods are returning one or several cards, the following format is used: <pre> array( 'id' => .., // the card ID 'type' => .., // the card type 'type_arg' => .., // the card type argument 'location' => .., // the card location 'location_arg' => .. // the card location argument ); </pre> === Picking cards === '''pickCard( $location, $player_id )''' Pick a card from a "pile" location (ex: "deck") and place it in the "hand" of specified player. Return the card picked or "null" if there are no more card in given location. This method supports auto-reshuffle (see "auto-reshuffle" below). '''pickCards( $nbr, $location, $player_id )''' Pick "$nbr" cards from a "pile" location (ex: "deck") and place them in the "hand" of specified player. Return an array with the cards picked, or "null" if there are no more card in given location. Note that the number of cards picked can be less than "$nbr" in case there are not enough cards in the pile location. This method supports auto-reshuffle (see "auto-reshuffle" below). In case there are not enough cards in the pile, all remaining cards are picked first, then the auto-reshuffle is triggered, then the other cards are picked. '''pickCardForLocation( $from_location, $to_location, $location_arg=0 )''' This method is similar to 'pickCard', except that you can pick a card for any sort of location and not only the "hand" location. * from_location is the "pile" style location from where you are picking a card. * to_location is the location where you will place the card picked. * if "location_arg" is specified, the card picked will be set with this "location_arg". This method supports auto-reshuffle (see "auto-reshuffle" below). '''pickCardsForLocation( $nbr, $from_location, $to_location, $location_arg=0, $no_deck_reform=false )''' This method is similar to 'pickCards', except that you can pick cards for any sort of location and not only the "hand" location. * from_location is the "pile" style location from where you are picking some cards. * to_location is the location where you will place the cards picked. * if "location_arg" is specified, the cards picked will be set with this "location_arg". * if "no_deck_reform" is set to "true", the auto-reshuffle feature is disabled during this method call. This method supports auto-reshuffle (see "auto-reshuffle" below). === Moving cards === '''moveCard( $card_id, $location, $location_arg=0 )''' Move the specific card to given location. * card_id: ID of the card to move. * location: location where to move the card. * location_arg: if specified, location_arg where to move the card. If not specified "location_arg" will be set to 0. '''moveCards( $cards, $location, $location_arg )''' Move the specific cards to given location. * cards: an array of IDs of cards to move. * location: location where to move the cards. * location_arg: if specified, location_arg where to move the cards. If not specified "location_arg" will be set to 0. '''insertCard( $card_id, $location, $location_arg )''' Move a card to a specific "pile" location where card are ordered. If location_arg place is already taken, increment all cards after location_arg in order to insert new card at this precise location. (note: insertCardOnExtremePosition method below is more useful in most of the case) '''insertCardOnExtremePosition( $card_id, $location, $bOnTop )''' Move a card on top or at bottom of given "pile" type location. '''moveAllCardsInLocation( $from_location, $to_location, $from_location_arg=null, $to_location_arg=0 )''' Move all cards in specified "from" location to given location. * from_location: where to take the cards * to_location: where to put the cards * from_location (optional): if specified, only cards with given "location_arg" are moved. * to_location (optional): if specified, cards moved "location_arg" is set to given value. Otherwise location_arg is set to zero. Note: if you want to keep "location_arg" untouched, you should use "moveAllCardsInLocationKeepOrder" below. '''moveAllCardsInLocationKeepOrder( $from_location, $to_location )''' Move all cards in specified "from" location to given "to" location. This method does not modify the "location_arg" of cards. '''playCard( $card_id )''' Move specified card at the top of the "discard" location. Note: this is an alias for: insertCardOnExtremePosition( $card_id, "discard", true ) === Get cards informations === '''getCard( $card_id )''' Get specific card information. Return null if this card is not found. '''getCards( $cards_array )''' Get specific cards information. cards_array is an array of cards ID. If some cards are not found or if some cards IDs are specified multiple times, the method throws an (unexpected) Exception. '''getCardsInLocation( $location, $location_arg = null, $order_by = null )''' Get all cards in specific location, as an array. Return an empty array if the location is empty. _ location (string): the location where to get the cards. _ location_arg (optional): if specified, return only cards with the specified "location_arg". _ order_by (optional): if specified, returned cards are ordered by the given database field. Example: "card_id" or "card_type". '''countCardInLocation( $location, $location_arg=null )''' Return the number of cards in specified location. _ location (string): the location where to count the cards. _ location_arg (optional): if specified, count only cards with the specified "location_arg". '''countCardsInLocations()''' Return the number of cards in each location of the game. The method returns an associative array with the format "location" => "number of cards". Example: <pre> array( 'deck' => 12, 'hand' => 21, 'discard' => 54, 'ontable' => 3 ); </pre> '''countCardsByLocationArgs( $location )''' Return the number of cards in each "location_arg" for the given location. The method returns an associative array with the format "location_arg" => "number of cards". Example: count the number of cards in each player's hand: <pre> countCardsByLocationArgs( 'hand' ); // Result: array( 122345 => 5, // player 122345 has 5 cards in hand 123456 => 4 // and player 123456 has 4 cards in hand ); </pre> '''getPlayerHand( $player_id )''' Get all cards in given player hand. Note: This is an alias for: getCardsInLocation( "hand", $player_id ) '''getCardOnTop( $location )''' Get the card on top of the given ("pile" style) location, or null if the location is empty. Note that the card pile won't be "auto-reshuffled" if there is no more card available. '''getCardsOnTop( $nbr, $location )''' Get the "$nbr" cards on top of the given ("pile" style) location. The method return an array with at most "$nbr" elements (or a void array if there is no card in this location). Note that the card pile won't be "auto-reshuffled" if there is not enough cards available. '''getExtremePosition( $bGetMax ,$location )''' (rarely used) Get the position of cards at the top of the given location / at the bottom of the given location. Of course this method works only on location in "pile" where you are using "location_arg" to specify the position of each card (example: "deck" location). If bGetMax=true, return the location of the top card of the pile. If bGetMax=false, return the location of the bottom card of the pile. '''getCardsOfType( $type, $type_arg=null )''' Get all cards of a specific type (rarely used). Return an array of cards, or an empty array if there is no cards of the specified type. _ type: the type of cards _ type_arg: if specified, return only cards with the specified "type_arg". === Shuffling === '''shuffle( $location )''' Shuffle all cards in specific location. Shuffle only works on locations where cards are on a "pile" (ex: "deck"). Please note that all "location_arg" will be reseted to reflect the new order of the cards in the pile. f4a855fc2b2063c8daae2d2cf77bbaf3876e6401 654 653 2013-02-13T17:04:14Z Sourisdudesert 1 /* Get cards informations */ wikitext text/x-wiki "Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side. Using "deck", you will be able to use the following features without writing a single SQL database request: * Place cards in pile, shuffle cards, draw cards one by one or many by many. * "Auto-reshuffle" discard pile into deck when deck is empty. * Move cards between different locations: hands of players, the table, ... == Using Deck: Hearts example == Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times. == Deck overview == With Deck component, you manage all cards of your game. === The 5 properties of each card === Using Deck component, each card will have 5 properties: * '''id''': This is the unique ID of each card. * '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?). * '''location''' and '''location_arg''': These two values defines where is the card at now. id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area. '''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game. '''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below. Examples of usage of "type" and "type_arg": * In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K). * In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used. * In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile. '''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer. You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs: * 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn). * 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player. * 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle"). Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game. === Create a new Deck component === For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql": <pre> CREATE TABLE IF NOT EXISTS `card` ( `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `card_type` varchar(16) NOT NULL, `card_type_arg` int(11) NOT NULL, `card_location` varchar(16) NOT NULL, `card_location_arg` int(11) NOT NULL, PRIMARY KEY (`card_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method: <pre> $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); </pre> Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game). Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method. "Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts": <pre> // Create cards $cards = array(); foreach( $this->colors as $color_id => $color ) // spade, heart, diamond, club { for( $value=2; $value<=14; $value++ ) // 2, 3, 4, ... K, A { $cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1); } } $this->cards->createCards( $cards, 'deck' ); </pre> As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument). Now, you are ready to use "Deck"! === Simple examples using Deck === (Most examples are from "Hearts" game) <pre> // In "getAllDatas', we need to send to the current player all the cards he has in hand: $result['hand'] = $this->cards->getCardsInLocation( 'hand', $player_id ); </pre> <pre> // At some time we want to check if all the cards (52) are in player's hands: if( $this->cards->countCardInLocation( 'hand' ) == 52 ) // do something </pre> <pre> // When a player plays a card in front of him on the table: $this->cards->moveCard( $card_id, 'cardsontable', $player_id ); // Note the use of the custom location 'cardsontable' here to keep track of cards on the table. </pre> <pre> // This is a new hand: let's gather all cards from everywhere in the deck: $this->cards->moveAllCardsInLocation( null, "deck" ); // And then shuffle the deck $this->cards->shuffle( 'deck' ); // And then deal 13 cards to each player // Deal 13 cards to each players // Create deck, shuffle it and give 13 initial cards $players = self::loadPlayersBasicInfos(); foreach( $players as $player_id => $player ) { $cards = $this->cards->pickCards( 13, 'deck', $player_id ); // Notify player about his cards self::notifyPlayer( $player_id, 'newHand', '', array( 'cards' => $cards ) ); } // Note the use of "notifyPlayer" instead of "notifyAllPlayers": new cards is a private information ;) </pre> == Deck component reference == === Initializing Deck component === '''init( $table_name )''' Initialize the Deck component. Argument: * table_name: name of the DB table used by this Deck component. Must be called before any other Deck method. Usually, init is called in your game constructor. Example with Hearts: <pre> function Hearts( ) { (...) $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); } </pre> '''createCards( $cards, $location='deck', $location_arg=null )''' Create card items in your deck component. Usually, all card items are created once, during the setup phase of the game. "cards" describe all cards that need to be created. "cards" is an array with the following format: <pre> // Create 1 card of type "1" with type_arg=99, // and 4 cards of type "2" with type_arg=12, // and 2 cards of type "3" with type_arg=33 $cards = array( array( 'type' => 1, 'type_arg' => 99, nbr' => 1 ), array( 'type' => 2, 'type_arg' => 12, nbr' => 4 ), array( 'type' => 3, 'type_arg' => 33, nbr' => 2 ) ... ); </pre> Note: During the "createCards" process, Deck generate unique IDs for all card items. Note: createCards is optimized to create a lot of cards at once. Do not use it to create cards one by one. If "location" and "location_arg" arguments are not set, newly created cards are placed in the "deck" location. If "location" (and optionally location_arg) is specified, cards are created for this specific location. === Card standard format === When Deck component methods are returning one or several cards, the following format is used: <pre> array( 'id' => .., // the card ID 'type' => .., // the card type 'type_arg' => .., // the card type argument 'location' => .., // the card location 'location_arg' => .. // the card location argument ); </pre> === Picking cards === '''pickCard( $location, $player_id )''' Pick a card from a "pile" location (ex: "deck") and place it in the "hand" of specified player. Return the card picked or "null" if there are no more card in given location. This method supports auto-reshuffle (see "auto-reshuffle" below). '''pickCards( $nbr, $location, $player_id )''' Pick "$nbr" cards from a "pile" location (ex: "deck") and place them in the "hand" of specified player. Return an array with the cards picked, or "null" if there are no more card in given location. Note that the number of cards picked can be less than "$nbr" in case there are not enough cards in the pile location. This method supports auto-reshuffle (see "auto-reshuffle" below). In case there are not enough cards in the pile, all remaining cards are picked first, then the auto-reshuffle is triggered, then the other cards are picked. '''pickCardForLocation( $from_location, $to_location, $location_arg=0 )''' This method is similar to 'pickCard', except that you can pick a card for any sort of location and not only the "hand" location. * from_location is the "pile" style location from where you are picking a card. * to_location is the location where you will place the card picked. * if "location_arg" is specified, the card picked will be set with this "location_arg". This method supports auto-reshuffle (see "auto-reshuffle" below). '''pickCardsForLocation( $nbr, $from_location, $to_location, $location_arg=0, $no_deck_reform=false )''' This method is similar to 'pickCards', except that you can pick cards for any sort of location and not only the "hand" location. * from_location is the "pile" style location from where you are picking some cards. * to_location is the location where you will place the cards picked. * if "location_arg" is specified, the cards picked will be set with this "location_arg". * if "no_deck_reform" is set to "true", the auto-reshuffle feature is disabled during this method call. This method supports auto-reshuffle (see "auto-reshuffle" below). === Moving cards === '''moveCard( $card_id, $location, $location_arg=0 )''' Move the specific card to given location. * card_id: ID of the card to move. * location: location where to move the card. * location_arg: if specified, location_arg where to move the card. If not specified "location_arg" will be set to 0. '''moveCards( $cards, $location, $location_arg )''' Move the specific cards to given location. * cards: an array of IDs of cards to move. * location: location where to move the cards. * location_arg: if specified, location_arg where to move the cards. If not specified "location_arg" will be set to 0. '''insertCard( $card_id, $location, $location_arg )''' Move a card to a specific "pile" location where card are ordered. If location_arg place is already taken, increment all cards after location_arg in order to insert new card at this precise location. (note: insertCardOnExtremePosition method below is more useful in most of the case) '''insertCardOnExtremePosition( $card_id, $location, $bOnTop )''' Move a card on top or at bottom of given "pile" type location. '''moveAllCardsInLocation( $from_location, $to_location, $from_location_arg=null, $to_location_arg=0 )''' Move all cards in specified "from" location to given location. * from_location: where to take the cards * to_location: where to put the cards * from_location (optional): if specified, only cards with given "location_arg" are moved. * to_location (optional): if specified, cards moved "location_arg" is set to given value. Otherwise location_arg is set to zero. Note: if you want to keep "location_arg" untouched, you should use "moveAllCardsInLocationKeepOrder" below. '''moveAllCardsInLocationKeepOrder( $from_location, $to_location )''' Move all cards in specified "from" location to given "to" location. This method does not modify the "location_arg" of cards. '''playCard( $card_id )''' Move specified card at the top of the "discard" location. Note: this is an alias for: insertCardOnExtremePosition( $card_id, "discard", true ) === Get cards informations === '''getCard( $card_id )''' Get specific card information. Return null if this card is not found. '''getCards( $cards_array )''' Get specific cards information. cards_array is an array of cards ID. If some cards are not found or if some cards IDs are specified multiple times, the method throws an (unexpected) Exception. '''getCardsInLocation( $location, $location_arg = null, $order_by = null )''' Get all cards in specific location, as an array. Return an empty array if the location is empty. * location (string): the location where to get the cards. * location_arg (optional): if specified, return only cards with the specified "location_arg". * order_by (optional): if specified, returned cards are ordered by the given database field. Example: "card_id" or "card_type". '''countCardInLocation( $location, $location_arg=null )''' Return the number of cards in specified location. * location (string): the location where to count the cards. * location_arg (optional): if specified, count only cards with the specified "location_arg". '''countCardsInLocations()''' Return the number of cards in each location of the game. The method returns an associative array with the format "location" => "number of cards". Example: <pre> array( 'deck' => 12, 'hand' => 21, 'discard' => 54, 'ontable' => 3 ); </pre> '''countCardsByLocationArgs( $location )''' Return the number of cards in each "location_arg" for the given location. The method returns an associative array with the format "location_arg" => "number of cards". Example: count the number of cards in each player's hand: <pre> countCardsByLocationArgs( 'hand' ); // Result: array( 122345 => 5, // player 122345 has 5 cards in hand 123456 => 4 // and player 123456 has 4 cards in hand ); </pre> '''getPlayerHand( $player_id )''' Get all cards in given player hand. Note: This is an alias for: getCardsInLocation( "hand", $player_id ) '''getCardOnTop( $location )''' Get the card on top of the given ("pile" style) location, or null if the location is empty. Note that the card pile won't be "auto-reshuffled" if there is no more card available. '''getCardsOnTop( $nbr, $location )''' Get the "$nbr" cards on top of the given ("pile" style) location. The method return an array with at most "$nbr" elements (or a void array if there is no card in this location). Note that the card pile won't be "auto-reshuffled" if there is not enough cards available. '''getExtremePosition( $bGetMax ,$location )''' (rarely used) Get the position of cards at the top of the given location / at the bottom of the given location. Of course this method works only on location in "pile" where you are using "location_arg" to specify the position of each card (example: "deck" location). If bGetMax=true, return the location of the top card of the pile. If bGetMax=false, return the location of the bottom card of the pile. '''getCardsOfType( $type, $type_arg=null )''' Get all cards of a specific type (rarely used). Return an array of cards, or an empty array if there is no cards of the specified type. * type: the type of cards * type_arg: if specified, return only cards with the specified "type_arg". === Shuffling === '''shuffle( $location )''' Shuffle all cards in specific location. Shuffle only works on locations where cards are on a "pile" (ex: "deck"). Please note that all "location_arg" will be reseted to reflect the new order of the cards in the pile. 888d00b0a38148f59e241b98b3bb921eba1403f2 Game interface logic: yourgamename.js 0 88 655 644 2013-02-13T17:07:00Z Sourisdudesert 1 wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> === Player's panel disabling/enabling '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 317bdc295b668f5ee01046885997fe77b6f0c0de 656 655 2013-02-13T17:07:21Z Sourisdudesert 1 /* Update players score */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 6c6bae4526ba6f719fe08686230ab499d1dbbec7 657 656 2013-02-13T17:07:28Z Sourisdudesert 1 /* Player's panel disabling/enabling */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Player's panel disabling/enabling == '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 2af44a5cdab3cfff195bc95c9cf3b64104568a06 673 657 2013-03-06T14:47:17Z Sourisdudesert 1 /* Players input */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Player's panel disabling/enabling == '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> bd972f271ef42252114b8f4d86ef99ebfc8ad83f 674 673 2013-03-06T14:52:26Z Sourisdudesert 1 /* Player's panel disabling/enabling */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Player's panel disabling/enabling == '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> bbdd8317ec1cbd390a37b6e0dbe5659007b947ff 676 674 2013-03-06T15:02:01Z Sourisdudesert 1 /* Player's panel disabling/enabling */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Reversi example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> bc879e9abee75c711f10c9937ff891393783156f 682 676 2013-03-06T15:18:06Z Sourisdudesert 1 /* General tips */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( node, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( $('cardcount'), _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( node, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Reversi example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> e1ea57068eed4a0c9bc22b8972fd0e776b21faee Gamehelpcoloretto 0 33 658 192 2013-02-14T22:53:02Z Peach 2372 wikitext text/x-wiki Während man im regulären Spiel entscheiden muss, welche Stapel positiv/negativ gewertet werden und wo man die Joker platziert, errechnet diese Version automatisch den höchst möglichen Score. 7f464fbdfa930182f9877ed6fef567378c23823a Faq 0 3 659 100 2013-02-15T07:41:51Z Larrygates 2403 /* What are the games available on BGA? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [[Board Game Arena club]] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple account and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had a bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. 437cf4ae7997f52afc3d4a93addca089139ad5f6 Practical debugging 0 100 660 632 2013-02-15T15:09:18Z Een 3 /* Javascript does not know how to sum two numbers */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> == Debugging my HTML/CSS layout == Situation examples: * why my game element doesn't show up in the interface? * why my CSS property hasn't been applied to this element? * why this game element is displayed at this position? A first useful tip when an element does not show up in the interface is to give it a red background: <pre> #my_element { ... some CSS definitions ... background-color: red; } </pre> This way, you know if the element is not visible because of some of its CSS property or because of anything else. Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property. Using Chrome "Elements" tab (thre first one), you can: * See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code. * Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles. * You can even modify directly some CSS property and see if how it looks immediately on the game interface. == Debugging my Javascript game interface logic == Compare to PHP debugging, Javascript debugging can sometimes be painful. Here's are some tips to make your life easier while developing and debugging Javascript: === Do complex things on PHP side === PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first. The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property. Note: check Reversi example for this. === Add traces in your code === You can use the following: '''console.log( variable_to_inspect )''' It will give you the object structure of the variable in the Javascript console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. '''alert( variable_to_inspect )''' It will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. == Some frequent errors == === when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." === Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. === when refreshing the web page, the interface remains on "Application loading..." === In this case, you probably have a syntax error in your Javascript code, and the interface refuses to load. To find this error, check if there is an error message in the Javascript console (F12). If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition. === When I do a move, I got "Move recorded, waiting for update ..." forever === "Move recorded" means that your ajaxcall request has been sent to the server and returned normally. "Waiting for update" means that your client interface is waiting for some notifications from the server that correspond to the move we just did. If this message stays forever, it is probably that your PHP code does not send any notification when the move happens, which is abnormal. To fix this: add a notifyAllPlayers or a notifyPlayer call in your PHP code. === Some player action is triggered randomly when I click somewhere on the game area === You probably used "dojo.connect" on a null object. In this case, dojo.connect associate the event (ex: "onclick") to the whole game area. Most of the time it happens in this situation, when my_object element does not exists: <pre> dojo.connect( $("my_object"), "onclick", this, function() { ... } </pre> To determine if this is the case, place "alert( $("my_object") )" before the dojo.connect to check if the object exists or not. === Javascript does not know how to sum two numbers === Be careful when you manipulate integers returned by notifications: most of the time, Javascript considers they are Strings and not Integers. As a result: <pre> var i=1; i += notif.args.increment; // With notif.args.increment='1' alert( i ); // i=11 instead of 2 !! Javascript concatenate 2 strings ! </pre> To solve this, you should use the "toint" function: <pre> var i=1; i += toint( notif.args.increment ); // With notif.args.increment='1' alert( i ); // i=2 :) </pre> === Javascript: do not use substr with negative numbers === To get the last characters of a string, use "slice" instead of "substr" which has a bug on IE: <pre> var three_last_characters = string.substr( -3 ); // Wrong var three_last_characters = string.slice( -3 ); // Correct </pre> d86a3fa2d7ac9e139610b3420fc0d619ea9fc38a Gamehelptroyes 0 26 661 649 2013-02-15T15:14:24Z Pablo74 19 /* Phase 1: Einkommen und Lohn */ wikitext text/x-wiki == Ziel == Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels. == Regel Zusammenfassung == (Diese Regel Zusammenfassung basiert auf der Spielhilfe von [http://boardgamegeek.com/user/pregremlin Andrew Agard] für Board Game Geek, unter Creative Commons Lizenz. Bitte schauen Sie [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] hier für Details. Vielen Dank Andrew !) ===Anfangs Aufstellung=== * Im Uhrzeigersinn werden werden die Bewohner in freie Felder der Gebäude gesetzt * Fahre gegen den Uhrzeigersinn fort, ausgehend vom letzten Spieler, bis alle Bewohner verteilt sind ===Spielablauf=== ====Phase 0: Aktionskarten aufdecken==== Decke die Aktionskarte für jede Karte entsprechend der aktuellen Runde auf (nur in den ersten 3 Runden) ====Phase 1: Einkommen und Lohn==== Erhalte 10 Deniers und zahle 1 Denier für jeden deiner Bewohner im Bischofssitz und 2 Deniers für jeden deiner Bewohner im Palast oder verliere 2 Siegespunkte ====Phase 2: Aufbau der arbeiterschaft==== Würfle mit gelbem/weißen/roten Würfel für jeden Bewohner im Rathaus/Bishopric/Palast und platziere ihn in deinem Bezirk ====Phase 3: Events==== Decke das oberste rote und weiße oder gelbe Event auf und platziere sie am rechten Ende der Reihe (unbegrenzte Events) Events nehmen Einfluss von links nach rechts * Military: start player takes 1 black die per die symbol * Other events: see annex (can’t execute: execute as much as possible and lose 2 VP) After Events, roll black dice and counter: * Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once * Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP) * In order players must counter highest remaining until all countered * Use any color dice. Double red dice. Can’t buy dice or use activity cubes ====Phase 4: Aktionen==== Siehe unten. ====Phase 5: Ende der Runde==== Nehme Deniers aus deinem Bezirk Return citizens lying on buildings to personal supplies Return unused dice to general supply Gib die Startspieler-Karte nach links ===Aktionen=== In order each player can use 1-3 matching dice for one action or pass. Round ends when no dice available or all players have passed May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice ====Aktionskarten aktivieren==== Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place citizen on free space (or illustration if full) from personal supply or any board location * 1 tradesman per player per card * Must activate at least once if tradesman hired * Citizens on card cannot be moved to newly freed space Immediate effect: activation cost (round down) determines color and use of dice Delayed effect: place cubes equal to activation cost. Use later (one cube per action) ====Construct Cathedral==== * Use 1-3 white dice to place 1-3 cubes on same-numbered construction site * Must place on lower levels before placing in higher levels for each set of valued spaces * Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6 ====Kampf Events==== * Activation cost (round down) defines dice and number of cubes to place on card * Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners Event countered when banners filled * Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards. * 2nd most cubes earns smaller reward (tied: total rounded down) * Most cubes takes card (tied: player who placed first). Discard if neutral has most * Marauding: rewards given, cubes removed, and then event is available again ====Platzieren einen Bewohner in einem Gebäude==== * Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value * Shift existing citizens to right. Citizens pushed off are laid on building illustration * If already have expelled citizen nobody can expel your citizens from that building ====Benutze Landwirtschaft==== * Erhalte eine Anzahl an Deniers gleich der Summe der Würfel durch 2 (abgerundet) ===Pass=== * If dice still in any city square, pass and receive 2 deniers which are placed in district * Each turn add another denier to district Have a good game ! 87a4c2e79c8cb54682718deadfb347051f4a4664 662 661 2013-02-15T15:15:46Z Pablo74 19 /* Phase 5: Ende der Runde */ wikitext text/x-wiki == Ziel == Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels. == Regel Zusammenfassung == (Diese Regel Zusammenfassung basiert auf der Spielhilfe von [http://boardgamegeek.com/user/pregremlin Andrew Agard] für Board Game Geek, unter Creative Commons Lizenz. Bitte schauen Sie [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] hier für Details. Vielen Dank Andrew !) ===Anfangs Aufstellung=== * Im Uhrzeigersinn werden werden die Bewohner in freie Felder der Gebäude gesetzt * Fahre gegen den Uhrzeigersinn fort, ausgehend vom letzten Spieler, bis alle Bewohner verteilt sind ===Spielablauf=== ====Phase 0: Aktionskarten aufdecken==== Decke die Aktionskarte für jede Karte entsprechend der aktuellen Runde auf (nur in den ersten 3 Runden) ====Phase 1: Einkommen und Lohn==== Erhalte 10 Deniers und zahle 1 Denier für jeden deiner Bewohner im Bischofssitz und 2 Deniers für jeden deiner Bewohner im Palast oder verliere 2 Siegespunkte ====Phase 2: Aufbau der arbeiterschaft==== Würfle mit gelbem/weißen/roten Würfel für jeden Bewohner im Rathaus/Bishopric/Palast und platziere ihn in deinem Bezirk ====Phase 3: Events==== Decke das oberste rote und weiße oder gelbe Event auf und platziere sie am rechten Ende der Reihe (unbegrenzte Events) Events nehmen Einfluss von links nach rechts * Military: start player takes 1 black die per die symbol * Other events: see annex (can’t execute: execute as much as possible and lose 2 VP) After Events, roll black dice and counter: * Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once * Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP) * In order players must counter highest remaining until all countered * Use any color dice. Double red dice. Can’t buy dice or use activity cubes ====Phase 4: Aktionen==== Siehe unten. ====Phase 5: Ende der Runde==== Nimm Deniers aus deinem Bezirk Nimm deine liegenden Bürger aus den Gebäuden in deinen persönlichen Vorrat Unbenutze Würfel gehen zurück in den allgemeinen Vorrat Gib die Startspieler-Karte nach links ===Aktionen=== In order each player can use 1-3 matching dice for one action or pass. Round ends when no dice available or all players have passed May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice ====Aktionskarten aktivieren==== Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place citizen on free space (or illustration if full) from personal supply or any board location * 1 tradesman per player per card * Must activate at least once if tradesman hired * Citizens on card cannot be moved to newly freed space Immediate effect: activation cost (round down) determines color and use of dice Delayed effect: place cubes equal to activation cost. Use later (one cube per action) ====Construct Cathedral==== * Use 1-3 white dice to place 1-3 cubes on same-numbered construction site * Must place on lower levels before placing in higher levels for each set of valued spaces * Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6 ====Kampf Events==== * Activation cost (round down) defines dice and number of cubes to place on card * Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners Event countered when banners filled * Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards. * 2nd most cubes earns smaller reward (tied: total rounded down) * Most cubes takes card (tied: player who placed first). Discard if neutral has most * Marauding: rewards given, cubes removed, and then event is available again ====Platzieren einen Bewohner in einem Gebäude==== * Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value * Shift existing citizens to right. Citizens pushed off are laid on building illustration * If already have expelled citizen nobody can expel your citizens from that building ====Benutze Landwirtschaft==== * Erhalte eine Anzahl an Deniers gleich der Summe der Würfel durch 2 (abgerundet) ===Pass=== * If dice still in any city square, pass and receive 2 deniers which are placed in district * Each turn add another denier to district Have a good game ! e8990947207bb3915058a4f1087c7046155f59bd 665 662 2013-02-21T15:08:59Z Peach 2372 /* Regel Zusammenfassung */ wikitext text/x-wiki == Ziel == Sei der Spieler mit den meisten Siegespunkten am Ende des Spiels. == Regel Zusammenfassung == (Diese Regel Zusammenfassung basiert auf der Spielhilfe von [http://boardgamegeek.com/user/pregremlin Andrew Agard] für Board Game Geek, unter Creative Commons Lizenz. Bitte schauen Sie [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] hier für Details. Vielen Dank Andrew !) ===Anfangs Aufstellung=== * Im Uhrzeigersinn werden werden die Bewohner in freie Felder der Gebäude gesetzt * Fahre gegen den Uhrzeigersinn fort, ausgehend vom letzten Spieler, bis alle Bewohner verteilt sind ===Spielablauf=== ====Phase 0: Aktionskarten aufdecken==== Decke die Aktionskarte für jede Karte entsprechend der aktuellen Runde auf (nur in den ersten 3 Runden) ====Phase 1: Einkommen und Lohn==== Erhalte 10 Deniers und zahle 1 Denier für jeden deiner Bewohner im Bischofssitz und 2 Deniers für jeden deiner Bewohner im Palast oder verliere 2 Siegespunkte ====Phase 2: Aufbau der Arbeiterschaft==== Würfle mit gelbem/weißen/roten Würfel für jeden Bewohner im Rathaus/Bishopric/Palast und platziere ihn in deinem Bezirk ====Phase 3: Events==== Decke das oberste rote und weiße oder gelbe Event auf und platziere sie am rechten Ende der Reihe (unbegrenzte Events) Events nehmen Einfluss von links nach rechts * Militär: Der Startspieler nimmt für jedes Würfelsymbol einen schwarzen Würfel * Andere Events: siehe Anhang (Bekämpfung nicht möglich: bekämpfe so viel wie möglich und verliere 2 Siegpunkte) Nach den Events, Rolle den schwarzen Würfel und kontere: * Startspieler muss den höchsten Wert mit einem oder mehreren Würfeln aus seinem Bezirk kontern. Gesamtwert muss >= Würfel sein. Mehrere Würfel gleichzeitig kontern ist möglich * Erhalte 1 Einflusspunkt für jeden gekonterten Würfel (kontern nicht möglich: entferne Würfel und verliere 2 Siegpunkte) * Im Uhrzeigersinn müssen die Spieler den höchsten übrig geblieben kontern bis alle gekontert sind * Benutze Würfel jeder Farbe. Rote Würfel werden verdoppelt. Würfel können nicht gekauft und Aktionen nicht ausgeübt werden. ====Phase 4: Aktionen==== Siehe unten. ====Phase 5: Ende der Runde==== Nimm Deniers aus deinem Bezirk Nimm deine liegenden Bürger aus den Gebäuden in deinen persönlichen Vorrat Unbenutze Würfel gehen zurück in den allgemeinen Vorrat Gib die Startspieler-Karte nach links ===Aktionen=== In order each player can use 1-3 matching dice for one action or pass. Round ends when no dice available or all players have passed May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice ====Aktionskarten aktivieren==== Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place citizen on free space (or illustration if full) from personal supply or any board location * 1 tradesman per player per card * Must activate at least once if tradesman hired * Citizens on card cannot be moved to newly freed space Immediate effect: activation cost (round down) determines color and use of dice Delayed effect: place cubes equal to activation cost. Use later (one cube per action) ====Construct Cathedral==== * Use 1-3 white dice to place 1-3 cubes on same-numbered construction site * Must place on lower levels before placing in higher levels for each set of valued spaces * Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6 ====Kampf Events==== * Activation cost (round down) defines dice and number of cubes to place on card * Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners Event countered when banners filled * Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards. * 2nd most cubes earns smaller reward (tied: total rounded down) * Most cubes takes card (tied: player who placed first). Discard if neutral has most * Marauding: rewards given, cubes removed, and then event is available again ====Platzieren einen Bewohner in einem Gebäude==== * Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value * Shift existing citizens to right. Citizens pushed off are laid on building illustration * If already have expelled citizen nobody can expel your citizens from that building ====Benutze Landwirtschaft==== * Erhalte eine Anzahl an Deniers gleich der Summe der Würfel durch 2 (abgerundet) ===Pass=== * If dice still in any city square, pass and receive 2 deniers which are placed in district * Each turn add another denier to district Have a good game ! 10e7539cf69405e6f021f88b33134b76ab2668a6 Gamehelpquoridor 0 102 663 2013-02-19T00:19:11Z Magicalvin 2439 Quoridor Request for Different Size Board wikitext text/x-wiki Hi,is it possible to edit the Quoridor board to different size board? ie 15x15 and different number of fences? ie 20 acbb73649bc695ffaf83329331452d7bab6fff75 664 663 2013-02-20T03:50:12Z Kaminix 2393 Page emptied (non-rule text) wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 666 664 2013-02-24T03:36:21Z Airandfingers 2504 wikitext text/x-wiki Corridor is a 2-player game, the object of which is to move your pawn to the other side of a 9x9 board. e5f5b0f70c54b52e359d958322b786afb0a71567 667 666 2013-02-28T09:23:03Z Magicalvin 2439 wikitext text/x-wiki Corridor is a 2-player game, the object of which is to move your pawn to the other side of a 9x9 board before your opponent. You can either move your man up,down or sideways or put a fence down. Players can jump over an opponent that he is next to or jump diagonally if he is next to a fence. Players cannot jump over fences. Players can put a fence down to block an opponent, but must allow at least one path to get to his winning side. You have only 10 fences. There is a fence counter by your name. Set traps to delay the opponent and create corridors to a winning path. You can concede the game by clicking on the square by your name and clicking "Concede...". You must have completed 50% or more of your game. There is an optional starting "Off the Center Aisle" Variation. Players agree to play this variation. The first player moves sideways and the second player move sideways in the opposite direction. The players keep on moving sideways until they agree to stop. 4adf60484c8ac4fea674576ec269f7e4d43c9364 695 667 2013-03-16T17:38:00Z Sirius136 2706 wikitext text/x-wiki [http://heyjude0929.pixnet.net/blog/post/26923277-%5B%E9%81%8A%E6%88%B2%E4%BB%8B%E7%B4%B9%5D%E6%AD%A5%E6%AD%A5%E7%82%BA%E7%87%9Fquoridor]步步為營(zh) Corridor is a 2-player game, the object of which is to move your pawn to the other side of a 9x9 board before your opponent. You can either move your man up,down or sideways or put a fence down. Players can jump over an opponent that he is next to or jump diagonally if he is next to a fence. Players cannot jump over fences. Players can put a fence down to block an opponent, but must allow at least one path to get to his winning side. You have only 10 fences. There is a fence counter by your name. Set traps to delay the opponent and create corridors to a winning path. You can concede the game by clicking on the square by your name and clicking "Concede...". You must have completed 50% or more of your game. There is an optional starting "Off the Center Aisle" Variation. Players agree to play this variation. The first player moves sideways and the second player move sideways in the opposite direction. The players keep on moving sideways until they agree to stop. 81f6185c44e295d3d224159201b0b4d3a368fc64 Kaozeal:Gamehelphearts 1 103 668 2013-03-02T23:23:01Z Chandler123 2569 Created page with "it seems to me that if you shoot the moon you should have the option to increase your own score or decrease the score of the other players" wikitext text/x-wiki it seems to me that if you shoot the moon you should have the option to increase your own score or decrease the score of the other players 5cd6ca4386ce8f33f76e892c009dd7ccc85c583b 671 668 2013-03-05T04:16:20Z Msome 2487 wikitext text/x-wiki chandler123: it seems to me that if you shoot the moon you should have the option to increase your own score or decrease the score of the other players. msome: That is common practice in the real world, but would make the length of an online game harder to predict, a problem for some players. I'd like to see an in-between solution: shooting the moon decreases the score of other players, unless doing so would end the game with you not in 1st place... in which case it instead increases your score by 26. In any case this discussion should be in the Forum, as I doubt anyone is reaing this talk page :) 7c6db170d1f2268afb4880b703201159b31b1afa Gamehelpseasons 0 43 669 185 2013-03-03T05:24:18Z Thoradian 997 wikitext text/x-wiki Season is a game of generating points (crystal) by choosing the correct combination of dice and the activation of card powers. The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be returned to the player on the starting of each cycle. Each player can choose only one die per turn. The effects are as follows: Star - increase the maximum card player can summon (max 15) Elements - Gain an energy of the element shown (water, earth, air, fire) Numbers - Gain the number of Crystals as indicated by the number Square card - Draw a card Dice with frames surrounding - Allow user to transmute energy into crystal (depend on which part of the game is at) Dots - Indicate how fast the marker progress through the seasons cycle There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There is 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice). At the end of the game the points are calculated by adding the numbers on each card and the crystal owned. The player with the most victory points wins. Note: Users need to discard energy immediately if the energy is more than the slots allocated. Card summon by other card but due to limitation of the star will cause the new card to be discarded, no refund. 5552e6fb806e97da9943bc61794ef1a78d500b88 Gamehelphearts 0 52 670 234 2013-03-05T04:08:41Z Msome 2487 moon /slam etiquette wikitext text/x-wiki Hearts is a card game for 4 players, every man for himself. It uses the standard 52-card pack. '''Rank''' A (high) to 2 (low). '''Setup''' The entire deck is dealt, giving you a hand of 13 cards. After looking at your hand, choose three cards to pass to another player. The passing rotation is: (1st hand) to the player on your left, (2nd hand) to the player across the table, (3rd hand) to the player on your right, (4th hand) no passing. The rotation repeats until the game ends. '''Tricks''' After passing cards, the player holding the 2 of clubs leads the first trick. Each player must follow suit if possible. If you have no cards of the suit led, you may play a card of any suit. Exception: You may not play a heart or the Queen of Spades on the first trick, even if you have no clubs. The highest card of the suit led wins the trick. The winner of a trick starts the next trick. Hearts may not be led until a heart has been played (this is called "breaking" hearts). The Queen of Spades may be lead at any time. [NB: In traditional Hearts, playing the Queen of Spades also breaks hearts.] There is no trump suit. '''Scoring''' At the end of each hand, each heart taken by a player counts -1, and the Queen of Spades counts -13. If one player has taken all 13 hearts ''and'' the Queen of Spades (this is known as "shooting the moon", or "slam"), that player scores 0 and all other players score -26. Warning other players about an attempt to shoot the moon is team play, and a breach of Hearts etiquette. When one or more players reach zero, the game ends. The player with the highest score wins. '''Variants''' Normal game is 100 points. Quick game is 75 points. 30e89bee40751176339d12f280b2f8d9cb48a3ca Gamehelptakenoko 0 104 672 2013-03-06T03:32:42Z Terrycloth 2601 Created page with "The game appears to think that the plot objectives are oriented. Since the rules say nothing about this it might be a bug." wikitext text/x-wiki The game appears to think that the plot objectives are oriented. Since the rules say nothing about this it might be a bug. 9008df23bbb966b1f34a0f89c9c6ade47840bd7a 696 672 2013-03-17T02:30:13Z Jirikki 2655 wikitext text/x-wiki Quick Reference Guide Each turn consists of 2 steps: 1) Determine weather 2) Perform 2 different actions and complete objectives Weather Types (always optional) Sun - take a 3rd action Rain - grow 1 bamboo on any irrigated plot Wind - take two identical actions Storm - move panda to any plot and he eats a bamboo as normal Clouds - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather for this turn Improvements can only be placed on plots with no bamboo. There can only be 1 improvement on a plot and once placed cannot be changed. Irrigation channels must be between two plots. When a plot is irrigated for the first time it grows bamboo. Plots can only be placed adjacent to the pond or where it is next to 2 other plots in play. The gardener grows bamboo on his plot and all adjacent irrigated plots of the same color. Game ends when a certain number of objectives have been completed. 2 players - 9 objectives 3 players - 8 objectives 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. fa07912e1a73702b1075cc1d4d35db8b91949a7d 697 696 2013-03-17T02:33:50Z Jirikki 2655 wikitext text/x-wiki Quick Reference Guide Each turn consists of 2 steps: 1) Determine weather 2) Perform 2 different actions and complete objectives Weather Types (always optional) Sun - take a 3rd action Rain - grow 1 bamboo on any irrigated plot Wind - take two identical actions Storm - move panda to any plot and he eats a bamboo as normal Clouds - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather for this turn Improvements can only be placed on plots with no bamboo. There can only be 1 improvement on a plot and once placed cannot be changed. Irrigation channels must be between two plots. When a plot is irrigated for the first time it grows bamboo. Plots can only be placed adjacent to the pond or where it is next to 2 other plots in play. The gardener grows bamboo on his plot and all adjacent irrigated plots of the same color. Game ends when a certain number of objectives have been completed. 2 players - 9 objectives 3 players - 8 objectives 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. 2b1801a348c4d02de75d3218816726ed3f00ca4a Translations 0 94 675 606 2013-03-06T14:56:14Z Sourisdudesert 1 /* How to not make translators crazy ;) */ wikitext text/x-wiki Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them. == How translation works? == When developing your game, all strings must be in English. Strings must be coherent with the English version of the game. Before the release of the game, BGA team will do the French translation of the game. After the release of the game, the BGA players community will translate the game in every language. == What should be translated? == Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ... This does NOT include error messages that are not supposed to happened (unexpected errors). == Focus on translating notifications == Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function. However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side. == WARNING: how to make sure your strings will be translated == For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers). If your original string is not "physically" inside one of this marker, it won't be translated. <pre> // Examples: the following strings will be translated: var mystring_translated = _("my string"); // JS $mystring_translated = self::_("my string"); // PHP $mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP // Examples: the following strings WILL NOT be translated: $my_string = "my string"; $not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation $not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing </pre> == How to not make translators crazy ;) == * When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings. * Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it). * Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like: <pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre> Write instead: <pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre> (or the equivalent "dojo.string.substitute" in Javascript) * When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings. * The BGA translation policy is to be flexible on grammar... We prefer to write "player gets 1 coin(s)" than write two versions of the same string for plural and singular - it reduces the number of strings to translate. * Instead of writing nice strings like "With the effect of ZZZ, player XXX gets a new YYY", which is very difficult to translate, write strings like "ZZZ: XXX gets YYY". == On client side (Javascript) == On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate. Examples: <pre> // Get a string in player's language: var translated = _("original english string"); // Get a string in player's language with parameter: var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", { p: 2, d: 4 } ); </pre> Note: what is also possible to do is == On server side (PHP) == On PHP side, you can use 3 different functions to specify that a string must be translated. '''clienttranslate( "my string to translate" ):''' This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side. In general, you use clienttranslate: * On your states.inc.php, for field "description" and "descriptionmyturn". <pre> "description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'), </pre> * On "material.inc.php", when defining texts for game material that must be displayed on client side. <pre> $this->card_types = array( 1 => array( 'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side. </pre> * When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation. <pre> // A game log string with no argument: self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() ); </pre> Translating arguments is a little bit more complex. It is using the "i18n" special argument as below: <pre> // In the following example, we translate the game log itself, but also the "card_name" argument: self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array( 'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'points' => $points, 'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string. ) ); </pre> '''self::_( "my string to translate" ):''' This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player). Most of the time, you don't need to translate strings on server side, except on the following 3 situations: * When throwing an exception because the player did a forbidden move. <pre> // This will display a translatable red message to the player that just do some wrong action: throw new feException( self::_('You must choose 3 cards'), true); // ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated. </pre> * In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file. <pre> $this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II"); </pre> * Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions. <pre> // In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this: throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true ); </pre> * Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user. '''totranslate( "my string to translate" ):''' This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side. You should not use this function, except on the following cases: * Statistics name in stats.inc.php * Option names and option values name in gameoptions.inc.php b93a5f713e0a56d8e521c6d6cc54a2520dffbb0f Stock 0 97 677 643 2013-03-06T15:05:36Z Sourisdudesert 1 wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: _ type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. _ weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted). _ image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_themeurl+'img/your_game_name/yourimage.png' </pre> _ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. '''onItemCreate''' Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it. Complete example: <pre> // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item: this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); (...) // And here is our "setupNewCard": setupNewCard: function( card_div, card_type_id, card_id ) { // Add a special tooltip on the card: this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' ); // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type // Add some custom HTML content INSIDE the Stock item: dojo.place( this.format_block( 'jstpl_my_card_content', { .... } ), card_div.id ); } </pre> == Tips when adding/removing items to/from Stock components == The usual way is the following: '''1st case''' When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from. '''2nd case''' When you add a card to a stock item, and this card is coming from another stock: * on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48". * then, remove the source item with "removeFromStockById". (note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide). '''3rd case''' When you move a card from a stock item to something that is not a stock item: * insert the card as a classic HTML template (dojo.place / this.format_block). * place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above). * slide it to its new position with "this.slideToObject" * remove the card from the Stock item with "removeFromStockById". Using the methods above, your cards should slided to, from and between your Stock controls smoothly 924af9cf8ebeed02fd579a8fa62baf6ca78c34f6 678 677 2013-03-06T15:06:03Z Sourisdudesert 1 /* Tips when adding/removing items to/from Stock components */ wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: _ type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. _ weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted). _ image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_themeurl+'img/your_game_name/yourimage.png' </pre> _ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. '''onItemCreate''' Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it. Complete example: <pre> // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item: this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); (...) // And here is our "setupNewCard": setupNewCard: function( card_div, card_type_id, card_id ) { // Add a special tooltip on the card: this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' ); // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type // Add some custom HTML content INSIDE the Stock item: dojo.place( this.format_block( 'jstpl_my_card_content', { .... } ), card_div.id ); } </pre> == Tips when adding/removing items to/from Stock components == The usual way is the following: '''Situation A''': When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from. '''Situation B''': When you add a card to a stock item, and this card is coming from another stock: * on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48". * then, remove the source item with "removeFromStockById". (note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide). '''Situation C''': When you move a card from a stock item to something that is not a stock item: * insert the card as a classic HTML template (dojo.place / this.format_block). * place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above). * slide it to its new position with "this.slideToObject" * remove the card from the Stock item with "removeFromStockById". Using the methods above, your cards should slided to, from and between your Stock controls smoothly 46fa0666b198c0c2ba93d6edcb88858e35fb57a7 699 678 2013-03-20T16:59:00Z Sourisdudesert 1 /* Complete stock component reference */ wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: _ type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. _ weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted). _ image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_themeurl+'img/your_game_name/yourimage.png' </pre> _ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method. '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. '''onItemCreate''' Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it. Complete example: <pre> // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item: this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); (...) // And here is our "setupNewCard": setupNewCard: function( card_div, card_type_id, card_id ) { // Add a special tooltip on the card: this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' ); // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type // Add some custom HTML content INSIDE the Stock item: dojo.place( this.format_block( 'jstpl_my_card_content', { .... } ), card_div.id ); } </pre> == Tips when adding/removing items to/from Stock components == The usual way is the following: '''Situation A''': When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from. '''Situation B''': When you add a card to a stock item, and this card is coming from another stock: * on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48". * then, remove the source item with "removeFromStockById". (note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide). '''Situation C''': When you move a card from a stock item to something that is not a stock item: * insert the card as a classic HTML template (dojo.place / this.format_block). * place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above). * slide it to its new position with "this.slideToObject" * remove the card from the Stock item with "removeFromStockById". Using the methods above, your cards should slided to, from and between your Stock controls smoothly a38bf1471a7860fdd10e302c07b6b1770bb18825 Main game logic: yourgamename.game.php 0 86 679 642 2013-03-06T15:09:36Z Sourisdudesert 1 /* Game states and active players */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method should be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this: <pre> $this->tie_breaker_description = self::_("Describe here your tie breaker formula"); </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. 53093afae2c0bf7fb0a989679b2b7f3977453591 680 679 2013-03-06T15:09:55Z Sourisdudesert 1 /* Game states and active players */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this: <pre> $this->tie_breaker_description = self::_("Describe here your tie breaker formula"); </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. 5f3667a959afcc309f1ac96079dcb6fa777af169 686 680 2013-03-06T15:32:43Z Sourisdudesert 1 wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this: <pre> $this->tie_breaker_description = self::_("Describe here your tie breaker formula"); </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. 7406f722579bbd5bcf3e69a11feb4e5ac8df0a76 687 686 2013-03-06T15:35:02Z Sourisdudesert 1 /* Zombie mode */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this: <pre> $this->tie_breaker_description = self::_("Describe here your tie breaker formula"); </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new feException( "Zombie mode not supported at this game state: ".$statename ); } </pre> 8897bcce501f79e77cb6106fb3652f3879e79803 688 687 2013-03-06T15:35:34Z Sourisdudesert 1 /* Zombie mode */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this: <pre> $this->tie_breaker_description = self::_("Describe here your tie breaker formula"); </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new feException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. 1bbaf94790e736345d32cf42d40095e027660046 Game interface stylesheet: yourgamename.css 0 96 681 634 2013-03-06T15:17:28Z Sourisdudesert 1 wikitext text/x-wiki This is the CSS stylesheet of your game User Interface. Styles defined on this file will be applied to the HTML elements you define in your HTML template (yourgame_yourgame.tpl), and to HTML elements you create dynamically with Javascript. Usually, you are using CSS to: 1°) define the overall layout of your game (ex: place the board on the top left, place player's hand beside, place the deck on the right, ...). 2°) create your CSS-sprites: All images of your games should be gathered into a small number of image files. Then, using background-image and background-position CSS properties, you create HTML blocks that can display these images correctly. Example: <pre> Example of CSS sprites (a black token and a white token, 20x20px each, embedded in the same "tokens.png" 40x20px image): .white_token { background-image: url('../../img/emptygame/tokens.png'); background-position: 0px 0px; } .black_token { background-image: url('../../img/emptygame/tokens.png'); background-position: -20px 0px; } .token { width: 20px; height: 20px; background-repeat: none; } </pre> 3°) ... anything else: It is really easy to add and remove CSS classes dynamically from your Javascript with dojo.addClass and dojo.removeClass. It is also easy to check if an element has a class (dojo.hasClass) or to get all elements with a specific class (dojo.query). This is why, very often, using CSS classes for the logic of your user interface allow you to do complex thing easily. Note: on the production platform, this file will be compressed and comments will be removed. Consequently, don't hesitate to put as many comments as necessary. Important: ALL the CSS directives for your game must be included in this CSS file. You can't create additional CSS files and import them. == spectatorMode == fd49cb098fa0e7edace88c6cc5445536ca0527ec 683 681 2013-03-06T15:20:58Z Sourisdudesert 1 /* spectatorMode */ wikitext text/x-wiki This is the CSS stylesheet of your game User Interface. Styles defined on this file will be applied to the HTML elements you define in your HTML template (yourgame_yourgame.tpl), and to HTML elements you create dynamically with Javascript. Usually, you are using CSS to: 1°) define the overall layout of your game (ex: place the board on the top left, place player's hand beside, place the deck on the right, ...). 2°) create your CSS-sprites: All images of your games should be gathered into a small number of image files. Then, using background-image and background-position CSS properties, you create HTML blocks that can display these images correctly. Example: <pre> Example of CSS sprites (a black token and a white token, 20x20px each, embedded in the same "tokens.png" 40x20px image): .white_token { background-image: url('../../img/emptygame/tokens.png'); background-position: 0px 0px; } .black_token { background-image: url('../../img/emptygame/tokens.png'); background-position: -20px 0px; } .token { width: 20px; height: 20px; background-repeat: none; } </pre> 3°) ... anything else: It is really easy to add and remove CSS classes dynamically from your Javascript with dojo.addClass and dojo.removeClass. It is also easy to check if an element has a class (dojo.hasClass) or to get all elements with a specific class (dojo.query). This is why, very often, using CSS classes for the logic of your user interface allow you to do complex thing easily. Note: on the production platform, this file will be compressed and comments will be removed. Consequently, don't hesitate to put as many comments as necessary. Important: ALL the CSS directives for your game must be included in this CSS file. You can't create additional CSS files and import them. == spectatorMode == When a spectator (= a player that is not part of the game) is viewing a game, the BGA framework add the CSS class "spectatorMode" to the wrapping HTML tag of your game. This way, if you want to apply a special style to some elements of your game for spectators, you can do this in your CSS: <pre> .spectatorMode #your_element_id { /* your special style */ } </pre> The most common usage of this is to hide some elements to spectators. For example, to hide "my hand" elements: <pre> .spectatorMode #my_hand { display: none; } </pre> 88bad6d7e34c7c8a69b27e76a3f8b8949b28656d Game layout: view and template: yourgamename.view.php and yourgamename yourgamename.tpl 0 98 684 602 2013-03-06T15:23:33Z Sourisdudesert 1 wikitext text/x-wiki These 2 files work together to provide the HTML layout of your game. Using these 2 files, you specify what HTML is rendered in your game client interface. In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser. Example: extract of "hearts_hearts.tpl": <pre> <div id="myhand_wrap" class="whiteblock"> <h3>{MY_HAND}</h3> <div id="myhand"> </div> </div> </pre> == WARNING == Your view and your template are supposed to generate only the BASE layout of the game You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :) Example of things to generate in your view: * The overall layout of your game interface (what is displayed where). * The board and fixed elements on the board (ex: places for cards, squares, ...). Example of things that shouldn't be generate by your view: * Game elements that come and go from the game area. * Game elements that are moving from one place to another. == phplib template system == BGA is using the phplib template system, used for example in PHPbb forums. More details about how to use phplib template system here: http://www.phpbuilder.com/columns/david20000512.php3 == Variables == In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value. In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}". To give a value to this variable in your view.php: Examples: <pre> // Display a translated version of "My hand" at the place of the variable in the template $this->tpl['MY_HAND'] = self::_("My hand"); // Display some raw HTML material at the place of the variable $this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" ); </pre> == Blocks == Using "blocks", you can repeat a piece of HTML from your template several time. You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares: <pre> (in reversi_reversi.tpl) <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> <div id="discs"> </div> </div> (in reversi.view.php) $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Explanations: * You specify a block in your template file, using "BEGIN" and "END" keywords. In the example above, we are creating a block named "square". * In your view, you declare your block using "begin_block" method. * Then, you can insert as many block as you want to, using "insert_block" method. The insert_block method takes 2 parameters: * the name of the block to insert. * an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP). == Nested blocks == You can use nested blocks. In the example below, we are going to add a mini-board for each player of the game, with 4 card places on each of it: <pre> (In template file) <!-- BEGIN player --> <div class="miniboard" id="miniboard_{PLAYER_ID}"> <div class="card_places"> <!-- BEGIN card_place --> <div id="card_place_{PLAYER_ID}_{PLACE_ID}"> </div> <!-- END card_place --> </div> </div> <!-- END player --> (In view file) $this->page->begin_block( "mygame_mygame.tpl", "card_place" ); // Nested block must be declared first $this->page->begin_block( "mygame_mygame.tpl", "player" ); foreach( $players as $player_id => $player ) { // Important: nested block must be reset here, otherwise the second player miniboard will // have 8 card_place, the third will have 12 card_place, and so one... $this->page->reset_subblocks( 'card_place' ); for( $i=1; $i<=4; $i++ ) { $this->page->insert_block( "card_place", array( 'PLAYER_ID' => $player_id, 'PLACE_ID' => $i ); } $this->page->insert_block( 'player', array( 'PLAYER_ID' => $player_id ); } </pre> == Javascript templates == For game elements that come and go from the game area, we suggest you to define a Javascript template. A Javascript template is defined in your template file like this: (Reversi Token from Reversi example): <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: a section for javascript templates is already available at the end of your template skeleton file. Then, you can use this javascript template to insert this piece of HTML in your game interface, like this: <pre> dojo.place( this.format_block( 'jstpl_disc', { xy: x+''+y, color: color } ) , 'discs' ); </pre> == How to access game information from .view.php? == From your .view.php, you can access the following: === Access current player id=== <pre> global $g_user; $current_player_id = $g_user->get_id(); </pre> === Access game object === In your view file, "$this->game" contains an instance of your main game class. Example: <pre> // Access to some game elements description described in your "material.inc.php": $my_cards_types = $this->game->card_types; // Access to any (public) method defined in my .game.php file: $result = $this->game->myMethod(); </pre> == Tips: display a nice button == From time to time, you need to display a standard button in your interface. BGA framework provides you a standard button that you can use directly in your interface: <pre> <a href="#" id="my_button_id" class="button"><span>My button label</span></a> </pre> Note: To see it in action, check for example a Coloretto game dfd849b48a11ad56d4e38edef008e0e22a155b02 685 684 2013-03-06T15:23:43Z Sourisdudesert 1 /* Tips: display a nice button */ wikitext text/x-wiki These 2 files work together to provide the HTML layout of your game. Using these 2 files, you specify what HTML is rendered in your game client interface. In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser. Example: extract of "hearts_hearts.tpl": <pre> <div id="myhand_wrap" class="whiteblock"> <h3>{MY_HAND}</h3> <div id="myhand"> </div> </div> </pre> == WARNING == Your view and your template are supposed to generate only the BASE layout of the game You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :) Example of things to generate in your view: * The overall layout of your game interface (what is displayed where). * The board and fixed elements on the board (ex: places for cards, squares, ...). Example of things that shouldn't be generate by your view: * Game elements that come and go from the game area. * Game elements that are moving from one place to another. == phplib template system == BGA is using the phplib template system, used for example in PHPbb forums. More details about how to use phplib template system here: http://www.phpbuilder.com/columns/david20000512.php3 == Variables == In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value. In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}". To give a value to this variable in your view.php: Examples: <pre> // Display a translated version of "My hand" at the place of the variable in the template $this->tpl['MY_HAND'] = self::_("My hand"); // Display some raw HTML material at the place of the variable $this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" ); </pre> == Blocks == Using "blocks", you can repeat a piece of HTML from your template several time. You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares: <pre> (in reversi_reversi.tpl) <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> <div id="discs"> </div> </div> (in reversi.view.php) $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Explanations: * You specify a block in your template file, using "BEGIN" and "END" keywords. In the example above, we are creating a block named "square". * In your view, you declare your block using "begin_block" method. * Then, you can insert as many block as you want to, using "insert_block" method. The insert_block method takes 2 parameters: * the name of the block to insert. * an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP). == Nested blocks == You can use nested blocks. In the example below, we are going to add a mini-board for each player of the game, with 4 card places on each of it: <pre> (In template file) <!-- BEGIN player --> <div class="miniboard" id="miniboard_{PLAYER_ID}"> <div class="card_places"> <!-- BEGIN card_place --> <div id="card_place_{PLAYER_ID}_{PLACE_ID}"> </div> <!-- END card_place --> </div> </div> <!-- END player --> (In view file) $this->page->begin_block( "mygame_mygame.tpl", "card_place" ); // Nested block must be declared first $this->page->begin_block( "mygame_mygame.tpl", "player" ); foreach( $players as $player_id => $player ) { // Important: nested block must be reset here, otherwise the second player miniboard will // have 8 card_place, the third will have 12 card_place, and so one... $this->page->reset_subblocks( 'card_place' ); for( $i=1; $i<=4; $i++ ) { $this->page->insert_block( "card_place", array( 'PLAYER_ID' => $player_id, 'PLACE_ID' => $i ); } $this->page->insert_block( 'player', array( 'PLAYER_ID' => $player_id ); } </pre> == Javascript templates == For game elements that come and go from the game area, we suggest you to define a Javascript template. A Javascript template is defined in your template file like this: (Reversi Token from Reversi example): <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: a section for javascript templates is already available at the end of your template skeleton file. Then, you can use this javascript template to insert this piece of HTML in your game interface, like this: <pre> dojo.place( this.format_block( 'jstpl_disc', { xy: x+''+y, color: color } ) , 'discs' ); </pre> == How to access game information from .view.php? == From your .view.php, you can access the following: === Access current player id=== <pre> global $g_user; $current_player_id = $g_user->get_id(); </pre> === Access game object === In your view file, "$this->game" contains an instance of your main game class. Example: <pre> // Access to some game elements description described in your "material.inc.php": $my_cards_types = $this->game->card_types; // Access to any (public) method defined in my .game.php file: $result = $this->game->myMethod(); </pre> == Tips: displaying a nice button == From time to time, you need to display a standard button in your interface. BGA framework provides you a standard button that you can use directly in your interface: <pre> <a href="#" id="my_button_id" class="button"><span>My button label</span></a> </pre> Note: To see it in action, check for example a Coloretto game a196c46198d60716daa784c0ab70e4b05830ccef Gamehelplibertalia 0 105 689 2013-03-13T13:45:03Z Peshte 2675 Created page with " == '''How to Play:''' == When it comes down to it, the actual game play of Libertalia is fair simple. Each player has a (mostly) identical set of crew cards. At the start of..." wikitext text/x-wiki == '''How to Play:''' == When it comes down to it, the actual game play of Libertalia is fair simple. Each player has a (mostly) identical set of crew cards. At the start of each round, one player deals out 9 crew members and reads them out loud to the rest of the players. Each other player then finds the same cards and pulls them into their hands. Thus, each round, players are playing with the same crew cards. Each crew card will have a strength (representing what order they choose their booty), and a special ability. Each card also has a tie breaker number, in case 2 players chose the same crew card. Once you have your hand of 9 cards, play begins. Each campaign is broken up into 6 days of looting. '''Each day has 4 phases: Phase 1: Sunrise Phase 2: Day Phase 3: Dusk Phase 4: Night''' '''''Phase 1: Sunrise''''' In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the main pirate ship in decreasing order. At this phase, any special actions that take place during sunrise would happen. Players also will need to use the tie breaker number on any crew cards if 2 or more people played the same crew member. '''''Phase 2: Day''''' The only thing that happens in this phase is any crew member with a day action, may take it, in increasing order of rank. (lowest goes first). '''''Phase 3: Dusk''''' Now, each player chooses a booty token from below the ship. Token are chosen in decreasing order of rank (the opposite of Phase 2). So your high ranking cards will get you the best tokens. Also, any dusk actions happen now. '''''Phase 4: Night''''' Once again, the only thing that happens in this phase is crew members may use their Night actions. The difference here though, is any crew members in your cabin, may still use their night actions. So that Barkeep card you played on day 1 of the current round, (his action is to score you 1 doubloon each night) will keep paying you each night of the campaign. Play those night cards early! After the 6th day of the campaign, the round is over. Players resolve any “end of campaign” actions of crew members till alive in their dens (yes, crew members can be killed). Then, each player adds up the value of their booty tokens and moves their score marker ahead on the track. To reset for the next campaign, all crew members used are removed from the game, all doubloons are returned to the bank (except 10) and all booty tokens returned to the bag. The key here is each player should have 3 cards left in their hand. They can use those in the next 2 campaigns. So everyone will have a somewhat different hand going forward. To start the next round, someone draws 6 new crew cards and everyone else takes the matching cards into their hand. Round 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner. fed7d8854a5c6ec97249e9f74e82bb1b264bbda4 690 689 2013-03-15T02:06:17Z Jirikki 2655 /* How to Play: */ wikitext text/x-wiki == '''How to Play:''' == In the first round, all players have an identical random set of 9 crew cards. For rounds 2 and 3, each player gets 6 identical cards to add to their 3 left over cards which may be different from the other players. Each crew card has a strength rating and a tie breaker number (representing what order they choose their booty), and a special ability. Crew are arranged with the lowest rating to highest, left to right. The games consists of 3 campaigns, broken up into 6 days of looting. '''Each day has 4 phases: Phase 1: Sunrise Phase 2: Day Phase 3: Dusk Phase 4: Night''' '''''Phase 1: Sunrise''''' In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the main pirate ship in decreasing order. At this phase, any special actions that take place during sunrise would happen. Players also will need to use the tie breaker number on any crew cards if 2 or more people played the same crew member. '''''Phase 2: Day''''' The only thing that happens in this phase is any crew member with a day action, may take it, in increasing order of rank. (lowest goes first). '''''Phase 3: Dusk''''' Now, each player chooses a booty token from below the ship. Token are chosen in decreasing order of rank (the opposite of Phase 2). So your high ranking cards will get you the best tokens. Also, any dusk actions happen now. '''''Phase 4: Night''''' Once again, the only thing that happens in this phase is crew members may use their Night actions. The difference here though, is any crew members in your cabin, may still use their night actions. So that Barkeep card you played on day 1 of the current round, (his action is to score you 1 doubloon each night) will keep paying you each night of the campaign. Play those night cards early! After the 6th day of the campaign, the round is over. Players resolve any “end of campaign” actions of crew members till alive in their dens (yes, crew members can be killed). Then, each player adds up the value of their booty tokens and moves their score marker ahead on the track. To reset for the next campaign, all crew members used are removed from the game, all doubloons are returned to the bank (except 10) and all booty tokens returned to the bag. The key here is each player should have 3 cards left in their hand. They can use those in the next 2 campaigns. So everyone will have a somewhat different hand going forward. To start the next round, someone draws 6 new crew cards and everyone else takes the matching cards into their hand. Round 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner. 4c777c2b3b9d498869f1c54787c435ab9785bb6d 691 690 2013-03-15T02:37:17Z Jirikki 2655 /* How to Play: */ wikitext text/x-wiki == '''How to Play:''' == The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases: Phase 1: Sunrise Phase 2: Day Phase 3: Dusk Phase 4: Night''' In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons. '''''Phase 1: Sunrise''''' In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right. '''''Phase 2: Day''''' The only thing that happens in this phase is all crew members with a day action MUST take it, in increasing order of rank. (lowest goes first). '''''Phase 3: Dusk''''' Each crew must claim a booty token from below the ship. Token are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed and action resolved (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed. '''''Phase 4: Night''''' The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early! After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns. To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward. Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner. 1a01f4d4b2394c68ed674410180a76eeed5666ba 692 691 2013-03-15T02:51:17Z Jirikki 2655 /* How to Play: */ wikitext text/x-wiki == '''How to Play:''' == The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases: Phase 1: Sunrise Phase 2: Day Phase 3: Dusk Phase 4: Night''' In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons. '''''Phase 1: Sunrise''''' In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right. '''''Phase 2: Day''''' The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first). '''''Phase 3: Dusk''''' Each crew must claim a booty token from below the ship. Token are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed. '''''Phase 4: Night''''' The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early! Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure. After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns. To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward. Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner. 71d48d5c00cb880cbfa1f5ce67e03c79c5e6fbc4 693 692 2013-03-15T09:27:35Z Jirikki 2655 /* How to Play: */ wikitext text/x-wiki Libertalia is an amazing and original card game. During three campaigns, you have to gather doubloons and booty tiles to become the wealthiest pirate. Each turn, you play one card to try to be the first to choose which share of the booty will be yours. Of course, each card has special powers that completely break this "routine". One thing that make Libertalia original is that everyone start with the same set of cards. That's why you'll have to choose carefully the moment to play each card, and to try to read your opponents' strategies. [[Link title]]== '''How to Play:''' == The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases: Phase 1: Sunrise Phase 2: Day Phase 3: Dusk Phase 4: Night''' In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons. '''''Phase 1: Sunrise''''' In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right. '''''Phase 2: Day''''' The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first). '''''Phase 3: Dusk''''' Each crew must claim a booty token from below the ship. Token are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed. '''''Phase 4: Night''''' The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early! Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure. After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns. To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward. Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner. 598bdc92946072ab19c78566b75e9983707d93ea Kaozeal:Gamehelpquoridor 1 106 694 2013-03-16T17:33:33Z Sirius136 2706 步步為營(zh) wikitext text/x-wiki [http://heyjude0929.pixnet.net/blog/post/26923277-%5B%E9%81%8A%E6%88%B2%E4%BB%8B%E7%B4%B9%5D%E6%AD%A5%E6%AD%A5%E7%82%BA%E7%87%9Fquoridor] a555fdcb2abc183558136d2652fdb38e4a8911cd Kaozeal:Gamehelptakenoko 1 107 698 2013-03-17T14:19:18Z Maman tuture 2711 Created page with "Guide de référence rapide Chaque tour se compose de 2 étapes: 1) Choisir le Types de temps 2) Achever des objectifs, en effectuant 2 actions différentes Types de temps (..." wikitext text/x-wiki Guide de référence rapide Chaque tour se compose de 2 étapes: 1) Choisir le Types de temps 2) Achever des objectifs, en effectuant 2 actions différentes Types de temps (toujours facultatif) : Soleil - prendre une 3ème action Pluie - cultiver 1 bambou sur n'importe quelle parcelle irrigué Vent - prendre deux actions identiques Tempête - déplacer le panda sur n'importe quelle parcelle,le panda mange un bambou comme d'habitude, si il n'y a pas d'aménagement d'interdiction de panda sur la parcelle Nuages ​​- choisir 1 des 4 autres types de temps pour ce tour ou prendre une puce d'aménagement Aménagements - Des aménagements peuvent être placés que sur des parcelles qui n'ont pas de bambou. Il ne peut y avoir qu'un aménagement par parcelle et une fois placé, ne peut pas être modifié. Actions : Parcelle - Les Parcelles ne peuvent être placés que de façon adjacents à l'étang ou lorsqu'elles sont à côté de 2 autres parcelles en jeu. Irrigation - Les canaux d'irrigation doivent être installé entre deux parcelles. Quand une parcelle est irriguée pour la première fois il y pousse un bambou. Jardinier - Le jardinier fait pousser du bambou sur la parcelle ou il se déplace et sur toutes les parcelles irriguées adjacentes de la même couleur et se déplace en ligne droite Panda - le panda mange un bambou, si il n'y a pas d'aménagement interdiction panda sur la parcelle et se déplace en ligne droite Le jeu se termine quand un certain nombre d'objectifs ont été réalisés. 2 joueurs - 9 objectifs 3 joueurs - 8 objectifs 4 joueurs - 7 objectifs Le premier joueur qui a compléter le nombre requis d'objectifs déclenche la phase finale et obtiens une carte bonus de 2 points supplémentaire. Les autres joueurs ont un tour final. Le score le plus élevé gagne, c'est la calcul du nombre de points sur les objectifs panda qui départage un score a égalité. Si le score reste toujours à égalité, tous les joueurs à égalité ont gagner. b9dd55bf908ecc24830088f1deb125a28474416c Stock 0 97 700 699 2013-03-20T16:59:47Z Sourisdudesert 1 /* Complete stock component reference */ wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: * type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. * weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted). * image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_themeurl+'img/your_game_name/yourimage.png' </pre> _ image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method. '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. '''onItemCreate''' Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it. Complete example: <pre> // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item: this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); (...) // And here is our "setupNewCard": setupNewCard: function( card_div, card_type_id, card_id ) { // Add a special tooltip on the card: this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' ); // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type // Add some custom HTML content INSIDE the Stock item: dojo.place( this.format_block( 'jstpl_my_card_content', { .... } ), card_div.id ); } </pre> == Tips when adding/removing items to/from Stock components == The usual way is the following: '''Situation A''': When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from. '''Situation B''': When you add a card to a stock item, and this card is coming from another stock: * on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48". * then, remove the source item with "removeFromStockById". (note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide). '''Situation C''': When you move a card from a stock item to something that is not a stock item: * insert the card as a classic HTML template (dojo.place / this.format_block). * place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above). * slide it to its new position with "this.slideToObject" * remove the card from the Stock item with "removeFromStockById". Using the methods above, your cards should slided to, from and between your Stock controls smoothly c61aed62adbb829cc6421e4d740a4d9eab88e1f5 701 700 2013-03-20T17:00:01Z Sourisdudesert 1 /* Complete stock component reference */ wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: * type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. * weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted). * image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_themeurl+'img/your_game_name/yourimage.png' </pre> * image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method. '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. '''onItemCreate''' Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it. Complete example: <pre> // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item: this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); (...) // And here is our "setupNewCard": setupNewCard: function( card_div, card_type_id, card_id ) { // Add a special tooltip on the card: this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' ); // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type // Add some custom HTML content INSIDE the Stock item: dojo.place( this.format_block( 'jstpl_my_card_content', { .... } ), card_div.id ); } </pre> == Tips when adding/removing items to/from Stock components == The usual way is the following: '''Situation A''': When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from. '''Situation B''': When you add a card to a stock item, and this card is coming from another stock: * on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48". * then, remove the source item with "removeFromStockById". (note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide). '''Situation C''': When you move a card from a stock item to something that is not a stock item: * insert the card as a classic HTML template (dojo.place / this.format_block). * place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above). * slide it to its new position with "this.slideToObject" * remove the card from the Stock item with "removeFromStockById". Using the methods above, your cards should slided to, from and between your Stock controls smoothly b31bae02a5f0ea27a4deff6893d5d96574136897 731 701 2013-04-08T12:33:20Z Sourisdudesert 1 /* Using stock: a simple example */ wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. At first, don't forget to add "ebg/stock" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <==== HERE ], </pre> The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_themeurl+'img/hearts/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: * type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. * weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted). * image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_themeurl+'img/your_game_name/yourimage.png' </pre> * image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method. '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. '''onItemCreate''' Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it. Complete example: <pre> // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item: this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); (...) // And here is our "setupNewCard": setupNewCard: function( card_div, card_type_id, card_id ) { // Add a special tooltip on the card: this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' ); // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type // Add some custom HTML content INSIDE the Stock item: dojo.place( this.format_block( 'jstpl_my_card_content', { .... } ), card_div.id ); } </pre> == Tips when adding/removing items to/from Stock components == The usual way is the following: '''Situation A''': When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from. '''Situation B''': When you add a card to a stock item, and this card is coming from another stock: * on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48". * then, remove the source item with "removeFromStockById". (note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide). '''Situation C''': When you move a card from a stock item to something that is not a stock item: * insert the card as a classic HTML template (dojo.place / this.format_block). * place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above). * slide it to its new position with "this.slideToObject" * remove the card from the Stock item with "removeFromStockById". Using the methods above, your cards should slided to, from and between your Stock controls smoothly 9052c361ca1eb2db288e379288080c355a3d2799 Your game state machine: states.inc.php 0 90 702 486 2013-03-23T10:33:02Z Tirix 1962 Corrected 'arg'=>'args' wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "args" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> === args === (optional) From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state. Example 1 : for Reversi, the list of possible moves during playerTurn state. Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor. Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them. In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them. Thus, this data can be transmitted to the clients and used by the clients to display it. Let's see a complete example using args with « Reversi » game : In states.inc.php, we specify some « args » argument for gamestate « playerTurn » : <pre> 10 => array( "name" => "placeWorkers", "description" => clienttranslate('${actplayer} must place some workers'), "descriptionmyturn" => clienttranslate('${you} must place some workers'), "type" => "activeplayer", "args" => "argPlaceWorkers", <================================== HERE "possibleactions" => array( "placeWorkers" ), "transitions" => array( "nextPlayer" => 11, "nextPhase" => 12, "zombiePass" => 11 ) ), </pre> It corresponds to a « argPlaceWorkers » method in our PHP code (reversi.game.php): <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves() ); } </pre> Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn : <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> Note: you can also used values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above). Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn). === updateGameProgression === (optional) IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated. At least one of your game state (any of them) must specify updateGameProgression=>true. 4223897f52eb3a5079cf418baa10823bc4df3b16 714 702 2013-03-28T17:34:44Z Sourisdudesert 1 /* args */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "args" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> === args === (optional) From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state. Example 1 : for Reversi, the list of possible moves during playerTurn state. Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor. Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them. In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them. Thus, this data can be transmitted to the clients and used by the clients to display it. Let's see a complete example using args with « Reversi » game : In states.inc.php, we specify some « args » argument for gamestate « playerTurn » : <pre> 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", <================================== HERE "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), </pre> It corresponds to a « argPlaceWorkers » method in our PHP code (reversi.game.php): <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves() ); } </pre> Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn : <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> Note: you can also used values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above). Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn). === updateGameProgression === (optional) IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated. At least one of your game state (any of them) must specify updateGameProgression=>true. ab9b17a0876a9a2f896473a45b3f21902d84d563 729 714 2013-04-05T02:46:37Z Pikiou 1872 /* args */ returned value from the arg function must be an associative array wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "args" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> === args === (optional) From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state. Example 1 : for Reversi, the list of possible moves during playerTurn state. Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor. Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them. In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them. Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array. Let's see a complete example using args with « Reversi » game : In states.inc.php, we specify some « args » argument for gamestate « playerTurn » : <pre> 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", <================================== HERE "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), </pre> It corresponds to a « argPlaceWorkers » method in our PHP code (reversi.game.php): <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves() ); } </pre> Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn : <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> Note: you can also used values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above). Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn). === updateGameProgression === (optional) IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated. At least one of your game state (any of them) must specify updateGameProgression=>true. 1e0d2ec9b66998ded171afa7edc9b10a50663aa9 Gamehelpcantstop 0 35 703 635 2013-03-24T14:06:08Z Een 3 Chinese translation moved to Chinese wiki wikitext text/x-wiki Can't Stop is a very easy and fast game! '''How to play''' Roll 4 standard dice and then choose the sums of any 2 dice to advance your position on the board. You are allowed to use 3 temporary markers to track your progress in columns marked 2 through 12. These markers are commonly white or black. You can continue to roll the dice hoping to roll one of the previous combinations in the three columns selected this turn. When you think you've pushed your luck far enough you say "STOP" then pass the dice to the next player and replace the white markers with your own. If you roll the dice and find no useful combination you fail and your progress is lost. The more common numbers on 2d6 (6,7 and 8) have more steps in their paths while the less common combinations (2 and 12) have fewer. '''The object of the game is''' to reach and cover 3 peaks of these columns! ed20a83da52065513f496d9eca15f358aaa88395 Gamehelpcaylus 0 37 704 108 2013-03-24T14:10:25Z Een 3 Rules link updated in the game page, obsolete information removed wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Gamehelpcoloretto 0 33 705 658 2013-03-24T14:13:28Z Een 3 Move German text to German wiki wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Gamehelpunitedsquare 0 42 706 155 2013-03-24T14:24:23Z Een 3 Adding info about colorblind preference wikitext text/x-wiki ==Goal== The goal is to be the player who has the most squares of his colors. ==Rules== The game contains multicolored squares (red, blue. yellow and green) which appear as 4 colored triangles on the square. Each player on his turn puts a multicolored square next to a square already on the board. The played square (which can be shifted to fit as requested, keeping the order of the colors the same) must be put in a way that creates at least on colored square (not necessarily your color). If it is not possible for the player to put down a square, the turn is passed to the next player. It is also possible to have "non playable" squares which are created when 2 of the same color are connected to the same open square. This is also a strategy to prevent from your opponent from getting more squares of his color. (e.g. if there is a red triangle facing an empty square and i connect to that same empty square another red triangle from another side, the empty square cannot be played and all colors around the "non playable" square will not become squares and won't gain points). ==Ending the game== When all playable squares have been played, the player with the most squares of his color wins the game. == Game preferences == The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD]. Learning the code is easy, just take a look at the following synthesis panel: [[File:ColorADD.jpg]] HAVE A GOOD GAME! ae79857f1a4a6c81a32e01211140a120a3b1acf4 707 706 2013-03-24T14:28:18Z Een 3 wikitext text/x-wiki ==Goal== The goal is to be the player who has the most squares of his colors. ==Rules== The game contains multicolored squares (red, blue. yellow and green) which appear as 4 colored triangles on the square. Each player on his turn puts a multicolored square next to a square already on the board. The played square (which can be shifted to fit as requested, keeping the order of the colors the same) must be put in a way that creates at least on colored square (not necessarily your color). If it is not possible for the player to put down a square, the turn is passed to the next player. It is also possible to have "non playable" squares which are created when 2 of the same color are connected to the same open square. This is also a strategy to prevent from your opponent from getting more squares of his color. (e.g. if there is a red triangle facing an empty square and i connect to that same empty square another red triangle from another side, the empty square cannot be played and all colors around the "non playable" square will not become squares and won't gain points). ==Ending the game== When all playable squares have been played, the player with the most squares of his color wins the game. == Game preferences == The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD]. Learning the code is easy, just take a look at the following synthesis panel: [[File:ColorADD.jpg]] '''HAVE A GOOD GAME!''' 694ca001b63acf097dcc5297944ab9994a7ef0b8 Gamehelptroyes 0 26 708 665 2013-03-24T14:51:54Z Een 3 Revert to English in the English wiki. German has been moved to the German wiki wikitext text/x-wiki == Goal == Be the player with the most victory points at the end of the game. == Rules summary == (This rules summary is based on the game help written by [http://boardgamegeek.com/user/pregremlin Andrew Agard] for Board Game Geek, under Creative Commons license. Please see [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] here for details. Thank you Andrew !) ===Initial Placement=== * In clockwise order place a citizen in empty space of one building * Continue in counter clockwise order from last player and so on until all citizens placed ===Game play=== ====Phase 0: Reveal the Activity cards==== Reveal activity card for each color corresponding to current round (first 3 rounds only) ====Phase 1: Income and salaries==== Receive 10 deniers and pay 1 per Bishopric and 2 per Palace citizen or lose 2 VP ====Phase 2: Assembling the workforce==== Roll yellow/white/red die per citizen in City Hall/Bishopric/Palace and place in district ====Phase 3: Events==== Reveal top red and white or yellow Event and place to right of queue (unlimited Events) Events take effect from left to right * Military: start player takes 1 black die per die symbol * Other events: see annex (can’t execute: execute as much as possible and lose 2 VP) After Events, roll black dice and counter: * Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once * Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP) * In order players must counter highest remaining until all countered * Use any color dice. Double red dice. Can’t buy dice or use activity cubes ====Phase 4: Actions==== See below. ====Phase 5: End of the round==== Receive deniers from district Return citizens lying on buildings to personal supplies Return unused dice to general supply Pass start player card left. ===Actions=== In order each player can use 1-3 matching dice for one action or pass. Round ends when no dice available or all players have passed May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice ====Activate Activity Card==== Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place citizen on free space (or illustration if full) from personal supply or any board location * 1 tradesman per player per card * Must activate at least once if tradesman hired * Citizens on card cannot be moved to newly freed space Immediate effect: activation cost (round down) determines color and use of dice Delayed effect: place cubes equal to activation cost. Use later (one cube per action) ====Construct Cathedral==== * Use 1-3 white dice to place 1-3 cubes on same-numbered construction site * Must place on lower levels before placing in higher levels for each set of valued spaces * Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6 ====Combat Events==== * Activation cost (round down) defines dice and number of cubes to place on card * Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners Event countered when banners filled * Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards. * 2nd most cubes earns smaller reward (tied: total rounded down) * Most cubes takes card (tied: player who placed first). Discard if neutral has most * Marauding: rewards given, cubes removed, and then event is available again ====Place a citizen on building==== * Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value * Shift existing citizens to right. Citizens pushed off are laid on building illustration * If already have expelled citizen nobody can expel your citizens from that building ====Use Agriculture==== * Gain number of deniers equal to total value divided by 2 (round down) ===Pass=== * If dice still in any city square, pass and receive 2 deniers which are placed in district * Each turn add another denier to district Have a good game ! fbdfaed8129e77bd038dee3623968940c24674a0 Tutorial gomoku 0 73 709 407 2013-03-24T18:38:25Z Een 3 /* Manage states and events */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created: [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( '../../img/gomoku/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * In .js->setup() assign the constants to this variable this.gameConstants = gamedatas.constants; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { // At the end of the slide, update the intersection dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'no_stone' ); dojo.addClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'stone_' + notif.args.color ); dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); // We can now destroy the stone since it is now visible through the change in style of the intersection dojo.destroy( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ); })); slide.play(); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, send a score update notification to the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 9d1e093ea97321f4d3cd5a98ab0acf194aa21aa5 Gamehelphaggis 0 22 710 48 2013-03-25T05:43:15Z Manchuwok 2352 /* Goal */ wikitext text/x-wiki == Goal == Earn more points than your opponent(s). Points may be earned by emptying your hand before the other players, capturing cards during play, and betting that you will be first to shed all of your cards. == Rules summary == A valid card combination may be a set, a sequence or a bomb: * a "set" is a group of any number of cards of the same rank (ex: one "8", two "5", ...). * a "sequence" is a group of 3 or more cards of the same color with consecutive rank (ex: red 8, red 9, red 10) * a "sequence" can also be a group of 2 or more pairs or larger sets of consecutive rank sharing the same suits between sets (ex: blue 3, green 3, blue 4, green 4, blue 5, green 5) * a "bomb" is one of the following combination (ranked below from lowest to highest): ** 3-5-7-9 (in 4 different colors, "rainbow bomb") ** J-Q ** J-K ** Q-K ** J-Q-K ** 3-5-7-9 (in one color, "suited bomb") Face cards can be used as wild cards to replace any cards in a "set" or a "sequence". Each player starts a round with a Jack, a Queen and a King. These face cards are public. At your turn, you have to play a higher ranking combination with exactly the same type and same number of card that the first combination played. You can also pass. Bombs are an exception: you can play a bomb to beat any combination, except a higher bomb. When all but one player pass in succession, the player who played the highest combination capture all cards played. Important exception: if the highest combination is a bomb, cards are captured by the player with the next higher combination. Then, a new trick starts. The winner of the last trick leads the new trick with any combination. ===Scoring overview=== * At the moment you shed your last card: 5 points per card in the hand of the player who held the most cards. * Cards captured values: 2-4-6-8-10 = 0 point, 3-5-7-9 = 1 point, J = 2 points, Q = 3 points, K = 5 points. * 30 points for a successful "Big bet", 15 points for a successful "Little bet". Points from unsuccessful bets are added to scores of the round's winner and to player(s) who did not bet. 154c77dae5ab153c37efd40d1286011b7c751d2a Gamehelplibertalia 0 105 711 693 2013-03-26T08:59:45Z Kevlarrelic 2786 Corrected some grammar in the introduction. I am an english teacher. It's what I do. :) wikitext text/x-wiki Libertalia is an amazing and original card game. During three campaigns, you have to gather doubloons and booty tiles to become the wealthiest pirate. Each turn, you play one card to try to be the first to choose which share of the booty will be yours. Of course, each card has special powers that completely break this "routine". One thing that makes Libertalia original is that everyone starts with the same set of cards. That's why you'll have to choose carefully which moment to play each card, and to try to read your opponents' strategies. [[Link title]]== '''How to Play:''' == The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases: Phase 1: Sunrise Phase 2: Day Phase 3: Dusk Phase 4: Night''' In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons. '''''Phase 1: Sunrise''''' In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right. '''''Phase 2: Day''''' The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first). '''''Phase 3: Dusk''''' Each crew must claim a booty token from below the ship. Token are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed. '''''Phase 4: Night''''' The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early! Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure. After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns. To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward. Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner. 869176603f34509754ff42de70dd9f95d2127be5 737 711 2013-04-08T16:12:40Z Nalafab 2897 wikitext text/x-wiki Libertalia is an amazing and original card game. During three campaigns, you have to gather doubloons and booty tiles to become the wealthiest pirate. Each turn, you play one card to try to be the first to choose which share of the booty will be yours. Of course, each card has special powers that completely break this "routine". One thing that makes Libertalia original is that everyone starts with the same set of cards. That's why you'll have to choose carefully which moment to play each card, and to try to read your opponents' strategies. == '''How to Play''' == The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases: Phase 1: Sunrise Phase 2: Day Phase 3: Dusk Phase 4: Night''' In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons. '''''Phase 1: Sunrise''''' In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right. '''''Phase 2: Day''''' The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first). '''''Phase 3: Dusk''''' Each crew must claim a booty token from below the ship. Token are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed. '''''Phase 4: Night''''' The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early! Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure. After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns. To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward. Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner. 47efc3c935f3f435ca534667540ffbd44fe68780 Grade 0 30 712 70 2013-03-26T19:47:56Z Doomquill 2742 /* All grades */ wikitext text/x-wiki Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. == All grades == * '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraph can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherub check that Seraph are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. * '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...) 8227839171a768ad8ec8be6d69d0eb3af8e1b5d4 Gamehelpseasons 0 43 713 669 2013-03-26T20:45:50Z Doomquill 2742 Clarification of rule: Cards are discarded with no refund if summoned by use of another card, but there is no room for them. wikitext text/x-wiki Season is a game of generating points (crystal) by choosing the correct combination of dice and the activation of card powers. The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be returned to the player on the starting of each cycle. Each player can choose only one die per turn. The effects are as follows: Star - increase the maximum card player can summon (max 15) Elements - Gain an energy of the element shown (water, earth, air, fire) Numbers - Gain the number of Crystals as indicated by the number Square card - Draw a card Dice with frames surrounding - Allow user to transmute energy into crystal (depend on which part of the game is at) Dots - Indicate how fast the marker progress through the seasons cycle There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There is 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice). At the end of the game the points are calculated by adding the numbers on each card and the crystal owned. The player with the most victory points wins. Note: Users need to discard energy immediately if the energy is more than the slots allocated. If a card allows you to summon another card but you have no space for this second card then it (the second card) will be discarded with no refund. e983a49ace608ec6898446f1ac07707648c0d7d4 Gamehelpsenet 0 108 715 2013-03-30T14:17:42Z Kara thrace 2819 Created page with " == Summary == Senet ("''The Game of Passing Through the Netherworld''") is well over 5000 yrs old, and is therefore most probably the oldest boardgame ever known. It comes f..." wikitext text/x-wiki == Summary == Senet ("''The Game of Passing Through the Netherworld''") is well over 5000 yrs old, and is therefore most probably the oldest boardgame ever known. It comes from the ancient Egypt, where it was used to amuse people and serve as a religional metaphor for the human souls' journey towards a blessed afterlife. Senet is an elegant and quick blocking game for 2 players, who compete against each other by moving their own pawns across a gameboard of thirty squares. Despite its old age, Senet turns out to be an amusing and tense little game for today's gamers aswell. == Goal == Move your stones (one at a time) on a reverse "S"'-shaped gametrack from the upper left to the lower right corner of the gameboard, where they can leave the gamearea. Be the first to bear all your stones off the gameboard to win! == The four "casting sticks" == The thrown sticks determine, how far you can move a stone during your turn. How to read the sticks: Count the sticks with their light sides up (results can be: 1, 2, 3 or 4). If no light sides show up at all - that's counted as a result of 5. Throwing values of 1, 4 and 5 grant Extra Turns. == Movement rules == If your stone lands on the opponent's unprotected stone, they swap places. You cannot land on a stone of your own colour. Two or more adjacent stones of the same colour protect each other. You always have to try to do a forward move. If this is not possible, you have to move one of your stones backwards. If you have NO valid moves to make at all - you loose your turn. Stones on the last 4 gamefields are never protected and cannot be moved - just borne off. == Special gamefields == Field 26 ('The House of Beauty'): All stones must STOP here on an exact throw, before they can go further. A stone standing here can be borne off the board on an exact throw of 5. Field 27 ('The House of Waters'): This is a pitfall! If you have a stone 'drowning' here, you have to decide whether to return the stone to Field 15 ('The House of Second Life') or to take the sticks and risk to throw a value of 4. (If you succeed to throw a 4 - the stone is borne off). Field 28 ('The House of Three Judges'): A stone standing here, can be borne off the board by an exact throw of 3. Field 29 ('The House of Two Judges'): A stone standing here, can be borne off the board by an exact throw of 2. Field 30 ('The House of Horus'): A stone standing here, can be borne off the board by ANY throw. If a stone is attacked on the last 3 gamefields, it is dropped into the "water" (unless the House of Waters is occupied already). Be the first to bear all your stones off the gameboard! d50b8a464add1615915b7573b6889b85318a277f 716 715 2013-03-30T14:18:07Z Kara thrace 2819 /* Special gamefields */ wikitext text/x-wiki == Summary == Senet ("''The Game of Passing Through the Netherworld''") is well over 5000 yrs old, and is therefore most probably the oldest boardgame ever known. It comes from the ancient Egypt, where it was used to amuse people and serve as a religional metaphor for the human souls' journey towards a blessed afterlife. Senet is an elegant and quick blocking game for 2 players, who compete against each other by moving their own pawns across a gameboard of thirty squares. Despite its old age, Senet turns out to be an amusing and tense little game for today's gamers aswell. == Goal == Move your stones (one at a time) on a reverse "S"'-shaped gametrack from the upper left to the lower right corner of the gameboard, where they can leave the gamearea. Be the first to bear all your stones off the gameboard to win! == The four "casting sticks" == The thrown sticks determine, how far you can move a stone during your turn. How to read the sticks: Count the sticks with their light sides up (results can be: 1, 2, 3 or 4). If no light sides show up at all - that's counted as a result of 5. Throwing values of 1, 4 and 5 grant Extra Turns. == Movement rules == If your stone lands on the opponent's unprotected stone, they swap places. You cannot land on a stone of your own colour. Two or more adjacent stones of the same colour protect each other. You always have to try to do a forward move. If this is not possible, you have to move one of your stones backwards. If you have NO valid moves to make at all - you loose your turn. Stones on the last 4 gamefields are never protected and cannot be moved - just borne off. == Special gamefields == * Field 26 ('The House of Beauty'): All stones must STOP here on an exact throw, before they can go further. A stone standing here can be borne off the board on an exact throw of 5. * Field 27 ('The House of Waters'): This is a pitfall! If you have a stone 'drowning' here, you have to decide whether to return the stone to Field 15 ('The House of Second Life') or to take the sticks and risk to throw a value of 4. (If you succeed to throw a 4 - the stone is borne off). * Field 28 ('The House of Three Judges'): A stone standing here, can be borne off the board by an exact throw of 3. * Field 29 ('The House of Two Judges'): A stone standing here, can be borne off the board by an exact throw of 2. * Field 30 ('The House of Horus'): A stone standing here, can be borne off the board by ANY throw. If a stone is attacked on the last 3 gamefields, it is dropped into the "water" (unless the House of Waters is occupied already). Be the first to bear all your stones off the gameboard! db8e2cd5d5a4e02c8a00c5ef8d237c29b86e91bb How to join BGA developer team? 0 83 717 521 2013-03-30T17:10:00Z Een 3 wikitext text/x-wiki Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your player user name on BGA * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf ''''terms & conditions' document''']. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: ''''I agree with the terms & conditions for developers on BGA Studio joined as an attachment''''. And of course, we also encourage you to tell us about which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, we'll discuss by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum) Second, once we have discussed together and are fixed on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a 'resources.html' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... that's all, you can start! cecd170b97b99a88d4541f8073f7d553d671aaf7 740 717 2013-04-13T12:27:37Z Een 3 wikitext text/x-wiki Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your player user name on BGA * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf ''''terms & conditions' document''']. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: ''''I agree with the terms & conditions for developers on BGA Studio joined as an attachment''''. And of course, we also encourage you to tell us about your developer experience and which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, we'll discuss by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum) Second, once we have discussed together and are set on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a ''''resources.html'''' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... well that's all, you can start! See [[Studio#Great.2C_I.27m_in.21_..._How_should_I_start.3F|Great, I'm in! ... How should I start?]] 9c82f85a3c558b3f7a584d879031b343438217f5 Game database model: dbmodel.sql 0 92 718 601 2013-03-31T13:24:39Z Rudolf 2790 /* Default tables */ wikitext text/x-wiki In this file you specify the database schema of your game. This file contains SQL queries that will be executed during the creation of your game table. Note: you can't change the database schema during the game. == Create your schema == To build this file, we recommend you to build the tables you need with the PhpMyAdmin tool (see BGA user guide), and then to export them and to copy/paste the content inside this file. == Default tables == Important: by default, BGA creates 4 tables for your game: global, stats, gamelog, and player. You must not modify the schema of global, stats and gamelog tables (and you must not access them directly with SQL queries in your PHP code). You may add columns to "player" table. This is very practical to add simple values associated with players. Example: <pre> ALTER TABLE `player` ADD `player_reserve_size` SMALLINT UNSIGNED NOT NULL DEFAULT '7'; </pre> For your information, the useful columns of default "player" table are: * player_no: the index of player in natural playing order. * player_id * player_name: (note: you should better access this date with getActivePlayerName() or loadPlayersBasicInfos() methods) * player_score: the current score of the player (displayed in the player panel). You must update this field to update player's scores. * player_score_aux: the secondary score, used as a tie breaker. You must update this field according to tie breaking rules of the game (see also: [[Main_game_logic:_yourgamename.game.php#Manage_player_scores_and_Tie_breaker|Manage_player_scores_and_Tie_breaker]]) == CREATE TABLES == you can create tables, using engine InnoDB <pre> CREATE TABLE IF NOT EXISTS `hands` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `player_id` TINYINT(1) NOT NULL, `1` BOOL NOT NULL DEFAULT 1, `2` BOOL NOT NULL DEFAULT 1, `3` BOOL NOT NULL DEFAULT 1, `4` BOOL NOT NULL DEFAULT 1, `5` BOOL NOT NULL DEFAULT 1, `6` BOOL NOT NULL DEFAULT 1, `7` BOOL NOT NULL DEFAULT 1, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> '''Note''': if you put comments, you cannot do it in same line than code, <pre> `3` BOOL NOT NULL DEFAULT 1, -- </pre> will comment also starting from `3` BOOL, and code will not be taken into account. == Link == You can add your Db inits in function SetupNewGame() from file 'gamename.game.php' == Errors Log == To trace Database creation, you've got a small summun up in red bars during the game, but details are in logs that you can access in /admin/studio. 2a8a849c1614262e9ba8dbfebfa54de8e18e4677 719 718 2013-03-31T13:26:02Z Rudolf 2790 /* CREATE TABLES */ activated wikitext text/x-wiki In this file you specify the database schema of your game. This file contains SQL queries that will be executed during the creation of your game table. Note: you can't change the database schema during the game. == Create your schema == To build this file, we recommend you to build the tables you need with the PhpMyAdmin tool (see BGA user guide), and then to export them and to copy/paste the content inside this file. == Default tables == Important: by default, BGA creates 4 tables for your game: global, stats, gamelog, and player. You must not modify the schema of global, stats and gamelog tables (and you must not access them directly with SQL queries in your PHP code). You may add columns to "player" table. This is very practical to add simple values associated with players. Example: <pre> ALTER TABLE `player` ADD `player_reserve_size` SMALLINT UNSIGNED NOT NULL DEFAULT '7'; </pre> For your information, the useful columns of default "player" table are: * player_no: the index of player in natural playing order. * player_id * player_name: (note: you should better access this date with getActivePlayerName() or loadPlayersBasicInfos() methods) * player_score: the current score of the player (displayed in the player panel). You must update this field to update player's scores. * player_score_aux: the secondary score, used as a tie breaker. You must update this field according to tie breaking rules of the game (see also: [[Main_game_logic:_yourgamename.game.php#Manage_player_scores_and_Tie_breaker|Manage_player_scores_and_Tie_breaker]]) == CREATE TABLES == you can create tables, using engine InnoDB <pre> CREATE TABLE IF NOT EXISTS `hands` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `player_id` TINYINT(1) NOT NULL, `1` BOOL NOT NULL DEFAULT 1, `2` BOOL NOT NULL DEFAULT 1, `3` BOOL NOT NULL DEFAULT 1, `4` BOOL NOT NULL DEFAULT 1, `5` BOOL NOT NULL DEFAULT 1, `6` BOOL NOT NULL DEFAULT 1, `7` BOOL NOT NULL DEFAULT 1, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> '''Note''': if you put comments, you cannot do it in same line than code, <pre> `3` BOOL NOT NULL DEFAULT 1, -- activated or not </pre> will comment also starting from `3` BOOL, and code will not be taken into account. == Link == You can add your Db inits in function SetupNewGame() from file 'gamename.game.php' == Errors Log == To trace Database creation, you've got a small summun up in red bars during the game, but details are in logs that you can access in /admin/studio. b66632e64543242efff3183de07348b143ce422d Studio 0 49 720 575 2013-03-31T13:31:10Z Rudolf 2790 /* Other components */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepare you 5 "powerpoint" presentations: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Tools and tips of BGA Studio]] [[Practical debugging]] [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 044e82a5e514797137b0960b427392296a307c6c 738 720 2013-04-13T12:20:43Z Een 3 /* Discover BGA Studio in 5 presentations */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Tools and tips of BGA Studio]] [[Practical debugging]] [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 49bd82e187e809424e09a921d09087648e29041a 739 738 2013-04-13T12:21:12Z Een 3 /* How to join the BGA developer team? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Tools and tips of BGA Studio]] [[Practical debugging]] [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] a639c5429d43182a1d03f41eb76931d1ee5e12ee 741 739 2013-04-13T12:28:58Z Een 3 /* Great, I'm in! ... How should I start? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we would advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Tools and tips of BGA Studio]] [[Practical debugging]] [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] c43891a136c278b4cc82d5a748fe45170d32aad5 742 741 2013-04-13T12:29:17Z Een 3 /* Great, I'm in! ... How should I start? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == [[Studio FAQ]] === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Tools and tips of BGA Studio]] [[Practical debugging]] [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 6dcd18e33a284bb4a37226504c1a3706163522ed 743 742 2013-04-13T12:30:15Z Een 3 /* BGA Studio documentation */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please ask them on the [http://forum.boardgamearena.com/viewforum.php?f=12 development forum]. == BGA Studio documentation == === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Tools and tips of BGA Studio]] [[Practical debugging]] [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 2d3092714cdd13c4a5f879634984870268c47799 744 743 2013-04-13T12:31:55Z Een 3 /* Great, I'm in! ... How should I start? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum''']. == BGA Studio documentation == === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hide. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a <div> element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Tools and tips of BGA Studio]] [[Practical debugging]] [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] f99220401e370693553bd434ceedcfd982b9b526 745 744 2013-04-13T12:34:53Z Een 3 /* BGA Studio game components reference */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum''']. == BGA Studio documentation == === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a &lt;div&gt; element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. [[Tools and tips of BGA Studio]] [[Practical debugging]] [[Studio back-office]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 893b70581489f7ff082e842dd3679fc3eebcb54f 746 745 2013-04-13T12:35:51Z Een 3 /* BGA Studio user guide */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum''']. == BGA Studio documentation == === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a &lt;div&gt; element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). == BGA Studio user guide == This part of the documentation is a user guide for the BGA Studio online development environment. [[Tools and tips of BGA Studio]] [[Practical debugging]] [[Studio back-office]] [[Studio FAQ]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 959f22824e9f3872dbf33d27215a865a48064e04 747 746 2013-04-13T12:36:20Z Een 3 /* BGA Studio user guide */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum''']. == BGA Studio documentation == === BGA Studio Framework reference === This part of the documentation focus on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a &lt;div&gt; element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). == BGA Studio user guide == This part of the documentation is a user guide for the BGA Studio online development environment. * [[Tools and tips of BGA Studio]] * [[Practical debugging]] * [[Studio back-office]] * [[Studio FAQ]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 9d2e8115976c14cc5292502715452c16a798e93a 749 747 2013-04-13T13:38:01Z Een 3 /* BGA Studio documentation */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum''']. == BGA Studio documentation == === BGA Studio Framework reference === This part of the documentation focuses on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a &lt;div&gt; element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). == BGA Studio user guide == This part of the documentation is a user guide for the BGA Studio online development environment. * [[Tools and tips of BGA Studio]] * [[Practical debugging]] * [[Studio back-office]] * [[Studio FAQ]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] d3aee79969dfa85c8c291868d0d0ca64cd86c429 Game replay 0 109 721 2013-03-31T13:31:32Z Rudolf 2790 Created page with "Game replay is managed by the framework (through replaying javascript notifications). You do not need to do anything special about it in your code." wikitext text/x-wiki Game replay is managed by the framework (through replaying javascript notifications). You do not need to do anything special about it in your code. 2152a2539ed7c895c8f6d92c2a5c3c17b21e2612 Tools and tips of BGA Studio 0 99 722 579 2013-03-31T13:44:45Z Rudolf 2790 Dev Tips wikitext text/x-wiki == Starting a game in one click == To start a game: * Create a new table with your game. * If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table. * Click on "Express Start". == Stopping a game in one click == * Click on the "quit" icon on the top right of the screen. * Click on "Express Stop". == Switching between users == when running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective. == Access to game database == Immediately at the bottom of the game area, the "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game. == Save & restore state == Using links of this section, you can save the complete current (database) state of your game, then restore it later. This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine. We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations. Limits: * the "restore" function does not work anymore when the game is over. * a saved situation from a given table cannot be restored in another table. * when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually. == Input/Output debugging section == This section shows you: * The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">" * The notifications received by your game interface. Notifications (inputs) begins with "<". Note: if you click on some notification title, you can resend it immediately to the user interface. == Run from the chat == On BGA Studio, you can directly run a PHP method from the chat. For example, if on your PHP you have this method: <pre> function giveMoneyToPlayer($player_id, $amount) { // Do some stuff } </pre> You can call this method directly from the chat like this: "giveMoneyToCurrentPlayer(2564,2)". == Dev Tips == '''Edit TPL''' <p> To edit TPL with HTML code highlightings in Gedit under Ubuntu: find gtksourceview directory in /usr/share, depending on your version (2.0, 3.0,...) Here it's 3.0, then type in a terminal window: <pre> sudo gedit /usr/share/gtksourceview-3.0/language-specs/html.lang </pre> then find 'globs' section, and change: <pre> <property name="globs">*.html;*.htm;*.tpl</property> </pre> 367271135966a60f7d8667032e164ba115fad7a7 723 722 2013-03-31T13:45:37Z Rudolf 2790 /* Dev Tips */ wikitext text/x-wiki == Starting a game in one click == To start a game: * Create a new table with your game. * If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table. * Click on "Express Start". == Stopping a game in one click == * Click on the "quit" icon on the top right of the screen. * Click on "Express Stop". == Switching between users == when running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective. == Access to game database == Immediately at the bottom of the game area, the "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game. == Save & restore state == Using links of this section, you can save the complete current (database) state of your game, then restore it later. This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine. We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations. Limits: * the "restore" function does not work anymore when the game is over. * a saved situation from a given table cannot be restored in another table. * when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually. == Input/Output debugging section == This section shows you: * The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">" * The notifications received by your game interface. Notifications (inputs) begins with "<". Note: if you click on some notification title, you can resend it immediately to the user interface. == Run from the chat == On BGA Studio, you can directly run a PHP method from the chat. For example, if on your PHP you have this method: <pre> function giveMoneyToPlayer($player_id, $amount) { // Do some stuff } </pre> You can call this method directly from the chat like this: "giveMoneyToCurrentPlayer(2564,2)". == Dev Tips == '''Edit TPL''' <p> To edit TPL with HTML code highlightings in Gedit under Ubuntu: find gtksourceview directory in /usr/share, depending on your version (2.0, 3.0,...).<p> Here it's 3.0, then type in a terminal window: <pre> sudo gedit /usr/share/gtksourceview-3.0/language-specs/html.lang </pre> then find 'globs' section, and change: <pre> <property name="globs">*.html;*.htm;*.tpl</property> </pre> dce08d9c2bca925f260d93beb64ba667c5346b0e 724 723 2013-03-31T13:47:11Z Rudolf 2790 /* Dev Tips */ wikitext text/x-wiki == Starting a game in one click == To start a game: * Create a new table with your game. * If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table. * Click on "Express Start". == Stopping a game in one click == * Click on the "quit" icon on the top right of the screen. * Click on "Express Stop". == Switching between users == when running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective. == Access to game database == Immediately at the bottom of the game area, the "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game. == Save & restore state == Using links of this section, you can save the complete current (database) state of your game, then restore it later. This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine. We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations. Limits: * the "restore" function does not work anymore when the game is over. * a saved situation from a given table cannot be restored in another table. * when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually. == Input/Output debugging section == This section shows you: * The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">" * The notifications received by your game interface. Notifications (inputs) begins with "<". Note: if you click on some notification title, you can resend it immediately to the user interface. == Run from the chat == On BGA Studio, you can directly run a PHP method from the chat. For example, if on your PHP you have this method: <pre> function giveMoneyToPlayer($player_id, $amount) { // Do some stuff } </pre> You can call this method directly from the chat like this: "giveMoneyToCurrentPlayer(2564,2)". == Dev Tips == '''Edit TPL''' <p> To edit TPL with HTML code highlightings in Gedit under Ubuntu: find gtksourceview directory in /usr/share, depending on your version (2.0, 3.0,...). <br> Here it's 3.0, then type in a terminal window: <pre> sudo gedit /usr/share/gtksourceview-3.0/language-specs/html.lang </pre> then find 'globs' section, and change: <pre> <property name="globs">*.html;*.htm;*.tpl</property> </pre> eabf6d0dd309c1cc92989ad27bf93d72ed46cafa Gamehelphearts 0 52 725 670 2013-04-02T09:29:12Z Deluxus 20 Srca - Hearts wikitext text/x-wiki Srca je igra z kartami za 4 igralce,ki jo igra vsak zase.Uporablja se standardni zavitek 52 kart. '''Moč kart''' A (najvišja) to 2 (najnižja). '''Priprava na igro''' Razdeli se celoten zavitek kart,vsak dobi 13 kart.Po pregledu 13 kart v rokah si izbereš 3 karte in jih podaš drugemu igralcu. Vrstni red podajanja 3 kart: (1 igra) igralcu na svoji levi, (2 igra) igralcu nasproti , (3 igra) igralcu na svoji desni, (4 igra) brez podajanja 3 kart. Vrstni red podajanja se ponavlja dokler igra ni končana. '''Igra''' Po podaji 3 kart, začne igralec ki ima v roki križevo 2. Vsak igralec mora slediti vrženi barvi.Če nima karte z isto bravo, lahko vrže katerokoli karto , katerekoli barve.Izjema : V prvem krogu ne mores vržti srca ali pikove Dame,če nimaš križa. Najvišja karta vzame vzetek.Igralec ki vzame vzetek vrže naslednjo karto. Srca iz roke ne smemo igrati dokler ne pade prvo srce,namesto druge barve.Pikova Dama pa se lahko igra kadarkoli. '''Točkovanje''' Po koncu vsakega kroga,vsako srce šteje -1 in pikova Dama -13. Če ima en igralec vseh 13 scr in pikovo Damo ,torej vse točkovne vzetke piše igralec 0, vsi ostali igralci pa pišejo -26. Kadar eden ali več igralcev pride na 0 ,je igra končana.Igralec z največ točkami zmaga. '''Variante igre''' Normal game je 100 točk. Quick game je 75 točk. 0fd9b27e12cc0e7c59b96f292587355a8c5a1f53 726 725 2013-04-02T09:31:13Z Deluxus 20 Srca wikitext text/x-wiki Srca je igra z kartami za 4 igralce,ki jo igra vsak zase.Uporablja se standardni zavitek 52 kart. '''Moč kart''' A (najvišja) do 2 (najnižja). '''Priprava na igro''' Razdeli se celoten zavitek kart,vsak dobi 13 kart.Po pregledu 13 kart v rokah si izbereš 3 karte in jih podaš drugemu igralcu. Vrstni red podajanja 3 kart: (1 igra) igralcu na svoji levi, (2 igra) igralcu nasproti , (3 igra) igralcu na svoji desni, (4 igra) brez podajanja 3 kart. Vrstni red podajanja se ponavlja dokler igra ni končana. '''Igra''' Po podaji 3 kart, začne igralec ki ima v roki križevo 2. Vsak igralec mora slediti vrženi barvi.Če nima karte z isto bravo, lahko vrže katerokoli karto , katerekoli barve.Izjema : V prvem krogu ne mores vržti srca ali pikove Dame,če nimaš križa. Najvišja karta vzame vzetek.Igralec ki vzame vzetek vrže naslednjo karto. Srca iz roke ne smemo igrati dokler ne pade prvo srce,namesto druge barve.Pikova Dama pa se lahko igra kadarkoli. '''Točkovanje''' Po koncu vsakega kroga,vsako srce šteje -1 in pikova Dama -13. Če ima en igralec vseh 13 src in pikovo Damo ,torej vse točkovne vzetke piše igralec 0, vsi ostali igralci pa pišejo -26. Kadar eden ali več igralcev pride na 0 ,je igra končana.Igralec z največ točkami zmaga. '''Variante igre''' Normal game je 100 točk. Quick game je 75 točk. 0af950fd94f906473c28158f37df8967fd0fe100 Game interface logic: yourgamename.js 0 88 727 682 2013-04-02T15:45:08Z Pikiou 1872 /* Tooltips */ addTooltip and addTooltipHtml get a node id, not a node element wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Reversi example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 87b3d23d52c75153c79cb900bcb8e2160e9aa782 728 727 2013-04-03T08:25:15Z Sourisdudesert 1 /* Players input */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Reversi example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 68e1bb2388e4f34a0f12444cca0b8e51a5072093 Scrollmap 0 110 730 2013-04-08T12:26:19Z Sourisdudesert 1 Created page with "Scrollmap is a BGA client side component to display an infinite game area. In many games, players are building the main game area with tiles or cards. Examples: * Carcassonne..." wikitext text/x-wiki Scrollmap is a BGA client side component to display an infinite game area. In many games, players are building the main game area with tiles or cards. Examples: * Carcassonne * Saboteur * Takenoko * Taluva * ... For tiles placement games when player are building , the board can be "infinite" cf4c11de919be13bbfdf77bb3e3610adf144ca01 732 730 2013-04-08T12:35:49Z Sourisdudesert 1 wikitext text/x-wiki Scrollmap is a BGA client side component to display an infinite game area. In some games, players are building the main game area with tiles or cards. Examples: * Carcassonne * Saboteur * Takenoko * Taluva * ... Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you. == Scrollmap in action == If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress. In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll. == How to use Scrollmap == At first, don't forget to add "ebg/scrollmap" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/scrollmap" /// <==== HERE ], </pre> Then, declare a new variable in your class for the Scrollmap object: <pre> constructor: function(){ console.log('yourgame constructor'); // Scrollable area this.scrollmap = new ebg.scrollmap(); </pre> f5870573733c23a47fbe7d00e3fe90f27b6a22f4 733 732 2013-04-08T12:54:34Z Sourisdudesert 1 /* How to use Scrollmap */ wikitext text/x-wiki Scrollmap is a BGA client side component to display an infinite game area. In some games, players are building the main game area with tiles or cards. Examples: * Carcassonne * Saboteur * Takenoko * Taluva * ... Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you. == Scrollmap in action == If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress. In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll. == How to use Scrollmap == At first, don't forget to add "ebg/scrollmap" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/scrollmap" /// <==== HERE ], </pre> Then, declare a new variable in your class for the Scrollmap object: <pre> constructor: function(){ console.log('yourgame constructor'); // Scrollable area this.scrollmap = new ebg.scrollmap(); </pre> Now, open your template (TPL) file and add this HTML code: <pre> <div id="map_container"> <div id="map_scrollable"></div> <div id="map_surface"></div> <div id="map_scrollable_oversurface"></div> <a id="movetop" href="#"></a> <a id="moveleft" href="#"></a> <a id="moveright" href="#"></a> <a id="movedown" href="#"></a> </div> </pre> Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method: <pre> // Make map scrollable this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') ); this.scrollmap.setupOnScreenArrows( 150 ); </pre> This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step. == Scrollable area layers == There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area: * inside "map_scrollable" div * inside "map_scrollable_oversurface" div The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice: * If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it. * If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element. Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason. 2ab80d98e101873cfc58e10bc94bde0a24ac0ee3 734 733 2013-04-08T12:55:28Z Sourisdudesert 1 /* Scrollable area layers */ wikitext text/x-wiki Scrollmap is a BGA client side component to display an infinite game area. In some games, players are building the main game area with tiles or cards. Examples: * Carcassonne * Saboteur * Takenoko * Taluva * ... Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you. == Scrollmap in action == If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress. In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll. == How to use Scrollmap == At first, don't forget to add "ebg/scrollmap" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/scrollmap" /// <==== HERE ], </pre> Then, declare a new variable in your class for the Scrollmap object: <pre> constructor: function(){ console.log('yourgame constructor'); // Scrollable area this.scrollmap = new ebg.scrollmap(); </pre> Now, open your template (TPL) file and add this HTML code: <pre> <div id="map_container"> <div id="map_scrollable"></div> <div id="map_surface"></div> <div id="map_scrollable_oversurface"></div> <a id="movetop" href="#"></a> <a id="moveleft" href="#"></a> <a id="moveright" href="#"></a> <a id="movedown" href="#"></a> </div> </pre> Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method: <pre> // Make map scrollable this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') ); this.scrollmap.setupOnScreenArrows( 150 ); </pre> This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step. == Scrollable area layers == There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area: * inside "map_scrollable" div * inside "map_scrollable_oversurface" div The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice: * If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it. * If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element. Of course, all layers are scrolled synchronously. Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason. 44346c9a67f3757698a18a3d64803996ff5685d5 735 734 2013-04-08T12:58:51Z Sourisdudesert 1 /* Scrollable area layers */ wikitext text/x-wiki Scrollmap is a BGA client side component to display an infinite game area. In some games, players are building the main game area with tiles or cards. Examples: * Carcassonne * Saboteur * Takenoko * Taluva * ... Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you. == Scrollmap in action == If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress. In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll. == How to use Scrollmap == At first, don't forget to add "ebg/scrollmap" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/scrollmap" /// <==== HERE ], </pre> Then, declare a new variable in your class for the Scrollmap object: <pre> constructor: function(){ console.log('yourgame constructor'); // Scrollable area this.scrollmap = new ebg.scrollmap(); </pre> Now, open your template (TPL) file and add this HTML code: <pre> <div id="map_container"> <div id="map_scrollable"></div> <div id="map_surface"></div> <div id="map_scrollable_oversurface"></div> <a id="movetop" href="#"></a> <a id="moveleft" href="#"></a> <a id="moveright" href="#"></a> <a id="movedown" href="#"></a> </div> </pre> Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method: <pre> // Make map scrollable this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') ); this.scrollmap.setupOnScreenArrows( 150 ); </pre> This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step. == Scrollable area layers == There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area: * inside "map_scrollable" div * inside "map_scrollable_oversurface" div The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice: * If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it. * If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element. Of course, all layers are scrolled synchronously. Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason. == Positioning elements on game area == All elements on the game are must be absolute positioned (with "top" and "left" attributes). By default, the game area is centered on 0,0 coordinates. e748822609d8cf4e816469a8a8b5eb157d898a16 736 735 2013-04-08T13:00:00Z Sourisdudesert 1 /* How to use Scrollmap */ wikitext text/x-wiki Scrollmap is a BGA client side component to display an infinite game area. In some games, players are building the main game area with tiles or cards. Examples: * Carcassonne * Saboteur * Takenoko * Taluva * ... Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you. == Scrollmap in action == If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress. In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll. == How to use Scrollmap == At first, don't forget to add "ebg/scrollmap" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/scrollmap" /// <==== HERE ], </pre> Then, declare a new variable in your class for the Scrollmap object: <pre> constructor: function(){ console.log('yourgame constructor'); // Scrollable area this.scrollmap = new ebg.scrollmap(); </pre> Now, open your template (TPL) file and add this HTML code: <pre> <div id="map_container"> <div id="map_scrollable"></div> <div id="map_surface"></div> <div id="map_scrollable_oversurface"></div> <a id="movetop" href="#"></a> <a id="moveleft" href="#"></a> <a id="moveright" href="#"></a> <a id="movedown" href="#"></a> </div> </pre> There are also some lines to add to your CSS stylesheet. Please note that you can adapt it to your needs, especially the default width of the scrollable area: <pre> /** Scrollable area **/ #map_container { position: relative; width: 100%; height: 400px; overflow: hidden; } #map_scrollable, #map_scrollable_oversurface { position: absolute; top: 205px; left: 315px; } #map_surface { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; cursor: move; } #map_footer { text-align: center; } </pre> Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method: <pre> // Make map scrollable this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') ); this.scrollmap.setupOnScreenArrows( 150 ); </pre> This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step. == Scrollable area layers == There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area: * inside "map_scrollable" div * inside "map_scrollable_oversurface" div The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice: * If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it. * If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element. Of course, all layers are scrolled synchronously. Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason. == Positioning elements on game area == All elements on the game are must be absolute positioned (with "top" and "left" attributes). By default, the game area is centered on 0,0 coordinates. eafd93396078275005cc7f744097c11c87c551a8 First steps with BGA Studio 0 111 748 2013-04-13T13:11:19Z Een 3 Created page with "== Connect to your SFTP folder and to the BGA Studio website == After your account has been created, you will get by email: * the name of the SFTP server to connect to * you..." wikitext text/x-wiki == Connect to your SFTP folder and to the BGA Studio website == After your account has been created, you will get by email: * the name of the SFTP server to connect to * your SFTP login and password * ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them. Using this information: # Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as WinSCP for example) # Check than in your home folder you have: #* One folder for each of the three example games (reversi, hearts, gomoku) #* One folder matching the game you will be developing #* One 'resources.html' file # Open the resources.html file, it contains #* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file #* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two) #* The URL pointing to the web administration tool for the BGA Studio database. # Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user. == Launch your game and check how to update it == # Find your game in the 'Play now' section and launch a table # Use the 'I want between X and X' players to tick down the maximum players number to the minimum # Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'. # Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save. # Go back to your browser and refresh, check that the game zone has updated. # Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game. # Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image. # Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated. == Commit your changes == That's all! Now you know about the basics of updating your game on the studio and testing your changes! 1f6096bf4d1c068292d042c0363a4fa2c952d352 Studio 0 49 750 749 2013-04-13T13:38:25Z Een 3 /* BGA Studio user guide */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the last information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum''']. == BGA Studio documentation == === BGA Studio Framework reference === This part of the documentation focuses on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a &lt;div&gt; element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. * [[Tools and tips of BGA Studio]] * [[Practical debugging]] * [[Studio back-office]] * [[Studio FAQ]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 33524cca8777e21c41c941b4b654ccc66ead291a 751 750 2013-04-13T13:38:56Z Een 3 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the latest information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum''']. == BGA Studio documentation == === BGA Studio Framework reference === This part of the documentation focuses on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a &lt;div&gt; element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. * [[Tools and tips of BGA Studio]] * [[Practical debugging]] * [[Studio back-office]] * [[Studio FAQ]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] cedd0f7bf28e85bb5b1e5f8b3c8524a1f6485e41 793 751 2013-04-29T13:09:31Z Sourisdudesert 1 wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the latest information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum''']. == BGA Studio documentation == === BGA Studio Framework reference === This part of the documentation focuses on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a &lt;div&gt; element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. * [[Tools and tips of BGA Studio]] * [[Practical debugging]] * [[Studio back-office]] * [[Studio FAQ]] == BGA Developer team organization == * [[Steps to create a BGA game]] * [[Post-release phase]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 09360c43e84cfb0fda9ec982df2ba3017f8ff4a1 First steps with BGA Studio 0 111 752 748 2013-04-13T13:40:33Z Een 3 /* Commit your changes */ wikitext text/x-wiki == Connect to your SFTP folder and to the BGA Studio website == After your account has been created, you will get by email: * the name of the SFTP server to connect to * your SFTP login and password * ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them. Using this information: # Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as WinSCP for example) # Check than in your home folder you have: #* One folder for each of the three example games (reversi, hearts, gomoku) #* One folder matching the game you will be developing #* One 'resources.html' file # Open the resources.html file, it contains #* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file #* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two) #* The URL pointing to the web administration tool for the BGA Studio database. # Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user. == Launch your game and check how to update it == # Find your game in the 'Play now' section and launch a table # Use the 'I want between X and X' players to tick down the maximum players number to the minimum # Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'. # Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save. # Go back to your browser and refresh, check that the game zone has updated. # Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game. # Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image. # Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated. == Commit your changes == Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development. Here is how to go through your first commit: # Go back to your browser tab showing the 'resources.html' file. Click on the URL pointing to the BGA Studio backoffice (do not log out of the BGA Studio website before doing so, or you will get a '''Not authorized''' error message as the authentication is shared); # Click on the 'Sources' menu entry to show the commit form. Enter your game name (under the same form as the name of your game folder: lowercase, no spaces), enter your commit comment (such as 'My first commit') then hit the 'Submit' button; # Check the log for errors, it should end with the following lines: Transmitting file data . Committed revision #revision number#. HAL says: done. NB: you should also commit each time you make an change to your gameoptions.inc.php file or to your stats.inc.php file, as an extra deployment action is needed from us for these files to take effect. Please mention in your commit comment that you need us to deploy those files, or send us an email to ask us to do it. == That's all for your first steps! == Now you know about the basics of updating your game on the studio and testing your changes. For more information on the specifics of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]]. 2859dd460cb4e3a04a35a5cddab674d8644efd66 753 752 2013-04-13T13:41:04Z Een 3 /* That's all for your first steps! */ wikitext text/x-wiki == Connect to your SFTP folder and to the BGA Studio website == After your account has been created, you will get by email: * the name of the SFTP server to connect to * your SFTP login and password * ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them. Using this information: # Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as WinSCP for example) # Check than in your home folder you have: #* One folder for each of the three example games (reversi, hearts, gomoku) #* One folder matching the game you will be developing #* One 'resources.html' file # Open the resources.html file, it contains #* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file #* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two) #* The URL pointing to the web administration tool for the BGA Studio database. # Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user. == Launch your game and check how to update it == # Find your game in the 'Play now' section and launch a table # Use the 'I want between X and X' players to tick down the maximum players number to the minimum # Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'. # Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save. # Go back to your browser and refresh, check that the game zone has updated. # Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game. # Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image. # Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated. == Commit your changes == Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development. Here is how to go through your first commit: # Go back to your browser tab showing the 'resources.html' file. Click on the URL pointing to the BGA Studio backoffice (do not log out of the BGA Studio website before doing so, or you will get a '''Not authorized''' error message as the authentication is shared); # Click on the 'Sources' menu entry to show the commit form. Enter your game name (under the same form as the name of your game folder: lowercase, no spaces), enter your commit comment (such as 'My first commit') then hit the 'Submit' button; # Check the log for errors, it should end with the following lines: Transmitting file data . Committed revision #revision number#. HAL says: done. NB: you should also commit each time you make an change to your gameoptions.inc.php file or to your stats.inc.php file, as an extra deployment action is needed from us for these files to take effect. Please mention in your commit comment that you need us to deploy those files, or send us an email to ask us to do it. == That's all! == Now you know about the basics of updating your game on the studio and testing your changes. For more information on the specifics of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]]. 4eb92e9d60a7f84791aa477080ee79603d07e860 754 753 2013-04-13T13:41:24Z Een 3 /* That's all! */ wikitext text/x-wiki == Connect to your SFTP folder and to the BGA Studio website == After your account has been created, you will get by email: * the name of the SFTP server to connect to * your SFTP login and password * ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them. Using this information: # Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as WinSCP for example) # Check than in your home folder you have: #* One folder for each of the three example games (reversi, hearts, gomoku) #* One folder matching the game you will be developing #* One 'resources.html' file # Open the resources.html file, it contains #* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file #* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two) #* The URL pointing to the web administration tool for the BGA Studio database. # Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user. == Launch your game and check how to update it == # Find your game in the 'Play now' section and launch a table # Use the 'I want between X and X' players to tick down the maximum players number to the minimum # Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'. # Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save. # Go back to your browser and refresh, check that the game zone has updated. # Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game. # Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image. # Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated. == Commit your changes == Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development. Here is how to go through your first commit: # Go back to your browser tab showing the 'resources.html' file. Click on the URL pointing to the BGA Studio backoffice (do not log out of the BGA Studio website before doing so, or you will get a '''Not authorized''' error message as the authentication is shared); # Click on the 'Sources' menu entry to show the commit form. Enter your game name (under the same form as the name of your game folder: lowercase, no spaces), enter your commit comment (such as 'My first commit') then hit the 'Submit' button; # Check the log for errors, it should end with the following lines: Transmitting file data . Committed revision #revision number#. HAL says: done. NB: you should also commit each time you make an change to your gameoptions.inc.php file or to your stats.inc.php file, as an extra deployment action is needed from us for these files to take effect. Please mention in your commit comment that you need us to deploy those files, or send us an email to ask us to do it. == That's all! == Now you know about the basics of updating your game on BGA Studio and testing your changes. For more information on the specifics of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]]. 745c7b8b5751da1fe807c4d42c47542fbcf1d6ad 775 754 2013-04-21T21:50:04Z Mlgx 2882 wikitext text/x-wiki == Connect to your SFTP folder and to the BGA Studio website == After your account has been created, you will get by email: * the name of the SFTP server to connect to * your SFTP login and password * ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them. Using this information: # Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as WinSCP for example) # Check that your home folder contains : #* One folder for each of the three example games (reversi, hearts, gomoku) #* One folder matching the game you will be developing #* One 'resources.html' file # Open the resources.html file, it contains : #* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file #* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two) #* The URL pointing to the web administration tool for the BGA Studio database. # Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user. == Launch your game and check how to update it == # Find your game in the 'Play now' section and launch a table # Use the 'I want between X and X' players to tick down the maximum players number to the minimum # Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'. # Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save. # Go back to your browser and refresh, check that the game zone has updated. # Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game. # Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image. # Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated. == Commit your changes == Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development. Here is how to go through your first commit: # Go back to your browser tab showing the 'resources.html' file. Click on the URL pointing to the BGA Studio backoffice (do not log out of the BGA Studio website before doing so, or you will get a '''Not authorized''' error message as the authentication is shared); # Click on the 'Sources' menu entry to show the commit form. Enter your game name (under the same form as the name of your game folder: lowercase, no spaces), enter your commit comment (such as 'My first commit') then hit the 'Submit' button; # Check the log for errors, it should end with the following lines: Transmitting file data . Committed revision #revision number#. HAL says: done. NB: you should also commit each time you make a change to your gameoptions.inc.php file or to your stats.inc.php file, as an extra deployment action is needed from us for these files to take effect. Please mention in your commit comment that you need us to deploy those files, or send us an email to ask us to do so. == That's all! == Now you know about the basics of updating your game on BGA Studio and testing your changes. For more information on the specificites of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]]. 99a92d5b3f86aa127525af0e3fc76e9abca6fef9 Gamehelpstoneage 0 21 755 135 2013-04-14T18:57:40Z Spacediver 718 /* Feed your people */ wikitext text/x-wiki == Goal == Get the most victory points at the end of the game. You win some points: * during the game, by acquiring buildings. * at the end of the game, according to civilization cards acquired by you. == Rules summary == Each round is divided into 3 phases, which are executed in the order described: 1. The players place their people on the game board. 2. The players use the actions of their placed people. 3. The players feed their people. ===Place your people on the game board=== Players place groups of their people in places, occupying each "ring" by one people (except for the forest place having no rings). Special rules for game with 2 players only: * no more than 1 player may occupy each of the following places: forest, clay pit, quarry, and river. * no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field Special rules for game with 3 players only: * no more than 2 players may occupy each of the following places: forest, clay pit, quarry, and river. * no more than 2 players may occupy '''the group''' of following places: tool maker, hut, and field ===Use the actions of your placed people=== Each player uses all his placed people in any order, and perform the corresponding actions: * '''hunting grounds, forest, clay pit, quarry, and river''': roll 1 dice per people placed and acquire corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river). * '''field''': increase agriculture level. * '''tool maker''': get one tool point (new tool is added, up to 3 in total, after that these tools are upgraded). * '''hut''': get one additional people. * '''building card''': buy the building with resources, scoring some points. * '''civilization card''': buy the card with a number of resources (of any kind) depending on its position (1 to 4 resources depicted above the card). Then the immediate effect of the card is applied. ===Resources=== hunting grounds, forest, clay pit, quarry, and river: Roll 1 dice per people and take corresponding resources: * 1 food for each full 2 on hunting grounds, * 1 wood for each full 3 on forest, * 1 brick for each full 4 on clay pit, * 1 stone for each full 5 on quarry, * 1 gold for each full 6 on river. You may use tools to increase the dice result and take more resources. ===Buildings=== Pay the building cost to get the building and receive points. If the building cost is not fixed (question mark in the corner of the card), you win points for each of the resources used to acquire this building, depending on their values (3 for each wood, 4 for each brick, ...). ===Civilization card details=== Each card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card). Place the mouse cursor on each card to see details in the tooltip. Note that at the list of your acquired civilization cards you will see only the bottom half of each card, for that top half is not relevant anymore. ===Feed your people=== Each agriculture level automatically give you 1 food. You must provide 1 food per person. You may use any resource to feed your people if there is not enough food. If you don't manage (or choose not) to feed your people by means above, you lose 10 points as a penalty. ===Game end=== The game ends when: * there are no more civilization cards at the beginning of a round * one building stack is empty at the end of a round Final number of points for each player is summed out of * points earned during the game by acquiring buildings, minus food penalties, * multipliers denoted at the bottom halfs of civilization cards collected (like number of different culture cards, number of people, tool level etc). * each resource that a player has on his player board scores 1 point 5921b3c6e17808ee318a02fc06ff06030a85b8f7 Gamehelplibertalia 0 105 756 737 2013-04-15T07:51:11Z Mantra 2943 /* How to Play */ wikitext text/x-wiki Libertalia is an amazing and original card game. During three campaigns, you have to gather doubloons and booty tiles to become the wealthiest pirate. Each turn, you play one card to try to be the first to choose which share of the booty will be yours. Of course, each card has special powers that completely break this "routine". One thing that makes Libertalia original is that everyone starts with the same set of cards. That's why you'll have to choose carefully which moment to play each card, and to try to read your opponents' strategies. == '''How to Play''' == The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases: Phase 1: Sunrise Phase 2: Day Phase 3: Dusk Phase 4: Night''' In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons. '''''Phase 1: Sunrise''''' In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right. '''''Phase 2: Day''''' The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first). '''''Phase 3: Dusk''''' Each crew must claim a booty token from below the ship. Tokens are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed. '''''Phase 4: Night''''' The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early! Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure. After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns. To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward. Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner. 1db47195e1202cd4d33fe0ee8d989c0b20b42c52 Gamehelpcantstop 0 35 757 703 2013-04-17T06:10:09Z Spheniscine 2908 wikitext text/x-wiki Can't Stop is a very easy and fast game! '''How to play''' Roll four standard dice. Divide them into two groups of two dice however you like, and advance on the appropriate track(s). You are allowed to use 3 temporary markers to track your progress in columns marked 2 through 12. These markers are commonly white or black. You can continue to roll the dice hoping to roll one of the previous combinations in the three columns selected this turn. When you think you've pushed your luck far enough you say "STOP" then pass the dice to the next player and replace the white markers with your own. If you roll the dice and find no useful combination you fail and your progress is lost. The more common numbers on 2d6 (6,7 and 8) have more steps in their paths while the less common combinations (2 and 12) have fewer. '''The object of the game is''' to reach and cover 3 peaks of these columns! f9c605bcf2b10f1518626fd7ce451fa440ce681c Main game logic: yourgamename.game.php 0 86 758 688 2013-04-18T14:32:20Z Pikiou 1872 /* Game states and active players */ Precision on setPlayersMultiactive wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this: <pre> $this->tie_breaker_description = self::_("Describe here your tie breaker formula"); </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new feException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. b9878cf2203fdcacd211b41f75d0f03be44bb80a Tutorial reversi 0 57 759 389 2013-04-19T12:36:14Z Garcia1968 2900 wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "states.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in state.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". d0f5fd5942831d1805c5cf65817d5dfdb0bbfba6 Gamehelpgearnpiston 0 112 760 2013-04-19T13:01:05Z Pikiou 1872 Created page with "=QUICK RULES REFERENCE= ==ROUND SEQUENCE AND PHASES== *I. Plan actions. *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ==LOCATION ACTIONS== *Back Alley: Choo..." wikitext text/x-wiki =QUICK RULES REFERENCE= ==ROUND SEQUENCE AND PHASES== *I. Plan actions. *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ==LOCATION ACTIONS== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (steal a part from another player), **or Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack. *Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Parts stack. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. ==REQUIREMENTS OF A COMPLETE AUTOMOBILE== * Each automobile requires a Motor, Fuel supply for each Motor, Steering, Gear and two Axles. * Each type of part (electric, gasoline, steam) requires a Motor and Supply of same type. * Each part on the top row requires a part on the bottom row and vice versa. * Each Axle supports only the five parts surrounding it. ==GAME END== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. ==SCORING== * VP according to Investors * +1 VP for each part in one largest continuous area * -1 VP for each point of Volatility 936ccfde729bfdf1af1090698d33ea21dacd50cd 761 760 2013-04-19T13:18:14Z Pikiou 1872 Smaller titles wikitext text/x-wiki ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Plan actions. *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (steal a part from another player), **or Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack. *Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Parts stack. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires a Motor, Fuel supply for each Motor, Steering, Gear and two Axles. * Each type of part (electric, gasoline, steam) requires a Motor and Supply of same type. * Each part on the top row requires a part on the bottom row and vice versa. * Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. ====SCORING==== * VP according to Investors * +1 VP for each part in one largest continuous area * -1 VP for each point of Volatility 9585ac256cef85265388481e8ff6f7409cf7dd8b 762 761 2013-04-19T13:20:28Z Pikiou 1872 Introduction sentence wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Plan actions. *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (steal a part from another player), **or Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack. *Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Parts stack. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires a Motor, Fuel supply for each Motor, Steering, Gear and two Axles. * Each type of part (electric, gasoline, steam) requires a Motor and Supply of same type. * Each part on the top row requires a part on the bottom row and vice versa. * Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. ====SCORING==== * VP according to Investors * +1 VP for each part in one largest continuous area * -1 VP for each point of Volatility 82f66c7de4d9a33ed8b6b26c761118881b4366ce 763 762 2013-04-19T21:22:24Z Jukka h 2977 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Plan actions. *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (steal a part from another player), **or Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack. *Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Parts stack. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires a Motor, Fuel supply for each Motor, Steering, Gear and two Axles. * Each type of part (electric, gasoline, steam) requires a Motor and Supply of same type. * Each part on the top row requires a part on the bottom row and vice versa. * Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. ====SCORING==== * VP according to Investors * +1 VP for each part in one largest continuous area * -1 VP for each point of Volatility 29595ee77bed2a188e6083d0ce260b31cc174dce 764 763 2013-04-20T12:31:19Z Jukka h 2977 /* QUICK RULES REFERENCE */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Plan actions. *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (steal a part from another player), **or Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack. *Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Parts stack. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires a Motor, Fuel supply for each Motor, Steering, Gear and two Axles. * Each type of part (electric, gasoline, steam) requires a Motor and Supply of same type. * Each part on the top row requires a part on the bottom row and vice versa. * Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. ====SCORING==== * VP according to Investors * +1 VP for each part in one largest continuous area * -1 VP for each point of Volatility ====BEGINNER TIPS==== * Keep an eye on what other players are doing. * Make sure to build often enough so you don't end up with a full hand and unspent actions. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action 0016c51475c81cf2ea3c5b6365bbd3fa798d1a44 765 764 2013-04-20T12:40:27Z Jukka h 2977 /* BEGINNER TIPS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Plan actions. *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (steal a part from another player), **or Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack. *Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Parts stack. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires a Motor, Fuel supply for each Motor, Steering, Gear and two Axles. * Each type of part (electric, gasoline, steam) requires a Motor and Supply of same type. * Each part on the top row requires a part on the bottom row and vice versa. * Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. ====SCORING==== * VP according to Investors * +1 VP for each part in one largest continuous area * -1 VP for each point of Volatility ====BEGINNER TIPS==== * Keep an eye on what other players are doing. * Make sure to build often enough so you don't end up with a full hand and unspent actions. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. * Reading the actual rules helps also. 9d79b0fec2d87cb081a91d56ee045243f429fad6 776 765 2013-04-23T07:33:19Z Lolinthedark 3013 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Plan actions. *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (steal a part from another player), **or Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack. *Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Junk Parts stack. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires a Motor, Fuel supply for each Motor, Steering, Gear and two Axles. * Each type of part (electric, gasoline, steam) requires a Motor and Supply of same type. * Each part on the top row requires a part on the bottom row and vice versa. * Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. ====SCORING==== * VP according to Investors * +1 VP for each part in one largest continuous area * -1 VP for each point of Volatility ====BEGINNER TIPS==== * Keep an eye on what other players are doing. * Make sure to build often enough so you don't end up with a full hand and unspent actions. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. * Reading the actual rules helps also. 350628121ba1bd4cd19bcc14ce0137a554a154d1 Scrollmap 0 110 766 736 2013-04-20T16:06:32Z Een 3 /* How to use Scrollmap */ wikitext text/x-wiki Scrollmap is a BGA client side component to display an infinite game area. In some games, players are building the main game area with tiles or cards. Examples: * Carcassonne * Saboteur * Takenoko * Taluva * ... Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you. == Scrollmap in action == If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress. In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll. == How to use Scrollmap == At first, don't forget to add "ebg/scrollmap" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/scrollmap" /// <==== HERE ], </pre> Then, declare a new variable in your class for the Scrollmap object: <pre> constructor: function(){ console.log('yourgame constructor'); // Scrollable area this.scrollmap = new ebg.scrollmap(); </pre> Now, open your template (TPL) file and add this HTML code: <pre> <div id="map_container"> <div id="map_scrollable"></div> <div id="map_surface"></div> <div id="map_scrollable_oversurface"></div> <a id="movetop" href="#"></a> <a id="moveleft" href="#"></a> <a id="moveright" href="#"></a> <a id="movedown" href="#"></a> </div> </pre> There are also some lines to add to your CSS stylesheet. Please note that you can adapt it to your needs, especially the default width of the scrollable area: <pre> /** Scrollable area **/ #map_container { position: relative; width: 100%; height: 400px; overflow: hidden; } #map_scrollable, #map_scrollable_oversurface { position: absolute; top: 205px; left: 315px; } #map_surface { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; cursor: move; } #map_footer { text-align: center; } /** Move arrows **/ #movetop,#moveleft,#moveright,#movedown { display: block; position: absolute; background-image: url('../../img/common/arrows.png'); width: 32px; height: 32px; } #movetop { top: 0px; left: 50%; background-position: 0px 32px; } #moveleft { top: 50%; left: 0px; background-position: 32px 0px; } #moveright { top: 50%; right: 0px; background-position: 0px 0px; } #movedown { bottom: 0px; left: 50%; background-position: 32px 32px; } </pre> Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method: <pre> // Make map scrollable this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') ); this.scrollmap.setupOnScreenArrows( 150 ); </pre> This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step. == Scrollable area layers == There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area: * inside "map_scrollable" div * inside "map_scrollable_oversurface" div The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice: * If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it. * If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element. Of course, all layers are scrolled synchronously. Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason. == Positioning elements on game area == All elements on the game are must be absolute positioned (with "top" and "left" attributes). By default, the game area is centered on 0,0 coordinates. 9bf1328defe1d592e843c1d52e57a4fb02f03b19 767 766 2013-04-20T16:08:47Z Een 3 /* How to use Scrollmap */ wikitext text/x-wiki Scrollmap is a BGA client side component to display an infinite game area. In some games, players are building the main game area with tiles or cards. Examples: * Carcassonne * Saboteur * Takenoko * Taluva * ... Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you. == Scrollmap in action == If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress. In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll. == How to use Scrollmap == At first, don't forget to add "ebg/scrollmap" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/scrollmap" /// <==== HERE ], </pre> Then, declare a new variable in your class for the Scrollmap object: <pre> constructor: function(){ console.log('yourgame constructor'); // Scrollable area this.scrollmap = new ebg.scrollmap(); </pre> Now, open your template (TPL) file and add this HTML code: <pre> <div id="map_container"> <div id="map_scrollable"></div> <div id="map_surface"></div> <div id="map_scrollable_oversurface"></div> <a id="movetop" href="#"></a> <a id="moveleft" href="#"></a> <a id="moveright" href="#"></a> <a id="movedown" href="#"></a> </div> </pre> There are also some lines to add to your CSS stylesheet. Please note that you can adapt it to your needs, especially the default width of the scrollable area: <pre> /** Scrollable area **/ #map_container { position: relative; width: 100%; height: 400px; overflow: hidden; } #map_scrollable, #map_scrollable_oversurface { position: absolute; top: 205px; left: 315px; } #map_surface { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; cursor: move; } #map_footer { text-align: center; } </pre> Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method: <pre> // Make map scrollable this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') ); this.scrollmap.setupOnScreenArrows( 150 ); </pre> This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step. == Scrollable area layers == There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area: * inside "map_scrollable" div * inside "map_scrollable_oversurface" div The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice: * If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it. * If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element. Of course, all layers are scrolled synchronously. Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason. == Positioning elements on game area == All elements on the game are must be absolute positioned (with "top" and "left" attributes). By default, the game area is centered on 0,0 coordinates. 8be1c95eca27e0a1f53cb9de14f88a8f439ebe46 768 767 2013-04-20T16:13:01Z Een 3 wikitext text/x-wiki Scrollmap is a BGA client side component to display an infinite game area. In some games, players are building the main game area with tiles or cards. Examples: * Carcassonne * Saboteur * Takenoko * Taluva * ... Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you. == Scrollmap in action == If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress. In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll. == How to use Scrollmap == At first, don't forget to add "ebg/scrollmap" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/scrollmap" /// <==== HERE ], </pre> Then, declare a new variable in your class for the Scrollmap object: <pre> constructor: function(){ console.log('yourgame constructor'); // Scrollable area this.scrollmap = new ebg.scrollmap(); </pre> Now, open your template (TPL) file and add this HTML code: <pre> <div id="map_container"> <div id="map_scrollable"></div> <div id="map_surface"></div> <div id="map_scrollable_oversurface"></div> <a id="movetop" href="#"></a> <a id="moveleft" href="#"></a> <a id="moveright" href="#"></a> <a id="movedown" href="#"></a> </div> </pre> There are also some lines to add to your CSS stylesheet. Please note that you can adapt it to your needs, especially the default width of the scrollable area: <pre> /** Scrollable area **/ #map_container { position: relative; width: 100%; height: 400px; overflow: hidden; } #map_scrollable, #map_scrollable_oversurface { position: absolute; top: 205px; left: 315px; } #map_surface { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; cursor: move; } #map_footer { text-align: center; } </pre> Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method: <pre> // Make map scrollable this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') ); this.scrollmap.setupOnScreenArrows( 150 ); </pre> This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step. == Scrollable area layers == There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area: * inside "map_scrollable" div * inside "map_scrollable_oversurface" div The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice: * If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it. * If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element. Of course, all layers are scrolled synchronously. Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason. == Positioning elements on game area == All elements on the game are must be absolute positioned (with "top" and "left" attributes). By default, the game area is centered on 0,0 coordinates. == Move arrows == To show move arrows around the scrollmap to enable click based navigation in addition to drag and drop, add these lines to your CSS <pre> /** Move arrows **/ #movetop,#moveleft,#moveright,#movedown { display: block; position: absolute; background-image: url('../../img/common/arrows.png'); width: 32px; height: 32px; } #movetop { top: 0px; left: 50%; background-position: 0px 32px; } #moveleft { top: 50%; left: 0px; background-position: 32px 0px; } #moveright { top: 50%; right: 0px; background-position: 0px 0px; } #movedown { bottom: 0px; left: 50%; background-position: 32px 32px; } </pre> Then, in your javascript, define the following functions <pre> onMoveTop : function( evt ) { console.log( "onMoveTop" ); evt.preventDefault(); this.scrollmap.scroll( 0, 300 ); }, onMoveLeft : function( evt ) { console.log( "onMoveLeft" ); evt.preventDefault(); this.scrollmap.scroll( 300, 0 ); }, onMoveRight : function( evt ) { console.log( "onMoveRight" ); evt.preventDefault(); this.scrollmap.scroll( -300, 0 ); }, onMoveDown : function( evt ) { console.log( "onMoveDown" ); evt.preventDefault(); this.scrollmap.scroll( 0, -300 ); }, </pre> And connect onclick events on the arrows to these functions in your javascript setup <pre> dojo.connect( $('movetop'), 'onclick', this, 'onMoveTop' ); dojo.connect( $('moveleft'), 'onclick', this, 'onMoveLeft' ); dojo.connect( $('moveright'), 'onclick', this, 'onMoveRight' ); dojo.connect( $('movedown'), 'onclick', this, 'onMoveDown' ); </pre> a5779da4f4a8368a11f8c98f9602ae601684abc8 769 768 2013-04-20T16:23:55Z Een 3 wikitext text/x-wiki Scrollmap is a BGA client side component to display an infinite game area. In some games, players are building the main game area with tiles or cards. Examples: * Carcassonne * Saboteur * Takenoko * Taluva * ... Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you. == Scrollmap in action == If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress. In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll. == How to use Scrollmap == At first, don't forget to add "ebg/scrollmap" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/scrollmap" /// <==== HERE ], </pre> Then, declare a new variable in your class for the Scrollmap object: <pre> constructor: function(){ console.log('yourgame constructor'); // Scrollable area this.scrollmap = new ebg.scrollmap(); </pre> Now, open your template (TPL) file and add this HTML code: <pre> <div id="map_container"> <div id="map_scrollable"></div> <div id="map_surface"></div> <div id="map_scrollable_oversurface"></div> <a id="movetop" href="#"></a> <a id="moveleft" href="#"></a> <a id="moveright" href="#"></a> <a id="movedown" href="#"></a> </div> </pre> There are also some lines to add to your CSS stylesheet. Please note that you can adapt it to your needs, especially the default width of the scrollable area: <pre> /** Scrollable area **/ #map_container { position: relative; width: 100%; height: 400px; overflow: hidden; } #map_scrollable, #map_scrollable_oversurface { position: absolute; top: 205px; left: 315px; } #map_surface { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; cursor: move; } #map_footer { text-align: center; } </pre> Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method: <pre> // Make map scrollable this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') ); this.scrollmap.setupOnScreenArrows( 150 ); </pre> This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step. == Scrollable area layers == There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area: * inside "map_scrollable" div * inside "map_scrollable_oversurface" div The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice: * If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it. * If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element. Of course, all layers are scrolled synchronously. Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason. == Positioning elements on game area == All elements on the game are must be absolute positioned (with "top" and "left" attributes). By default, the game area is centered on 0,0 coordinates. == Enable move arrows == To show move arrows icons around the scrollmap in order to enable click based navigation in addition to drag and drop, add these lines to your CSS: <pre> /** Move arrows **/ #movetop,#moveleft,#moveright,#movedown { display: block; position: absolute; background-image: url('../../img/common/arrows.png'); width: 32px; height: 32px; } #movetop { top: 0px; left: 50%; background-position: 0px 32px; } #moveleft { top: 50%; left: 0px; background-position: 32px 0px; } #moveright { top: 50%; right: 0px; background-position: 0px 0px; } #movedown { bottom: 0px; left: 50%; background-position: 32px 32px; } </pre> In your javascript, define the following functions: <pre> onMoveTop : function( evt ) { console.log( "onMoveTop" ); evt.preventDefault(); this.scrollmap.scroll( 0, 300 ); }, onMoveLeft : function( evt ) { console.log( "onMoveLeft" ); evt.preventDefault(); this.scrollmap.scroll( 300, 0 ); }, onMoveRight : function( evt ) { console.log( "onMoveRight" ); evt.preventDefault(); this.scrollmap.scroll( -300, 0 ); }, onMoveDown : function( evt ) { console.log( "onMoveDown" ); evt.preventDefault(); this.scrollmap.scroll( 0, -300 ); }, </pre> And connect onclick events on the arrows to these functions in your javascript setup <pre> dojo.connect( $('movetop'), 'onclick', this, 'onMoveTop' ); dojo.connect( $('moveleft'), 'onclick', this, 'onMoveLeft' ); dojo.connect( $('moveright'), 'onclick', this, 'onMoveRight' ); dojo.connect( $('movedown'), 'onclick', this, 'onMoveDown' ); </pre> 5ab6faa990a4c4f66cd6235581c04cef32f984db 780 769 2013-04-26T13:53:16Z Een 3 wikitext text/x-wiki Scrollmap is a BGA client side component to display an infinite game area. In some games, players are building the main game area with tiles or cards. Examples: * Carcassonne * Saboteur * Takenoko * Taluva * ... Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you. == Scrollmap in action == If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress. In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll. == How to use Scrollmap == At first, don't forget to add "ebg/scrollmap" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/scrollmap" /// <==== HERE ], </pre> Then, declare a new variable in your class for the Scrollmap object: <pre> constructor: function(){ console.log('yourgame constructor'); // Scrollable area this.scrollmap = new ebg.scrollmap(); </pre> Now, open your template (TPL) file and add this HTML code: <pre> <div id="map_container"> <div id="map_scrollable"></div> <div id="map_surface"></div> <div id="map_scrollable_oversurface"></div> <a id="movetop" href="#"></a> <a id="moveleft" href="#"></a> <a id="moveright" href="#"></a> <a id="movedown" href="#"></a> </div> </pre> There are also some lines to add to your CSS stylesheet. Please note that you can adapt it to your needs, especially the default width of the scrollable area: <pre> /** Scrollable area **/ #map_container { position: relative; width: 100%; height: 400px; overflow: hidden; } #map_scrollable, #map_scrollable_oversurface { position: absolute; top: 205px; left: 315px; } #map_surface { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; cursor: move; } #map_footer { text-align: center; } </pre> Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method: <pre> // Make map scrollable this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') ); this.scrollmap.setupOnScreenArrows( 150 ); </pre> This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step. == Scrollable area layers == There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area: * inside "map_scrollable" div * inside "map_scrollable_oversurface" div The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice: * If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it. * If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element. Of course, all layers are scrolled synchronously. Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason. == Positioning elements on game area == All elements on the game are must be absolute positioned (with "top" and "left" attributes). By default, the game area is centered on 0,0 coordinates. == Enable move arrows == To show move arrows icons around the scrollmap in order to enable click based navigation in addition to drag and drop, add these lines to your CSS: <pre> /** Move arrows **/ #movetop,#moveleft,#moveright,#movedown { display: block; position: absolute; background-image: url('../../img/common/arrows.png'); width: 32px; height: 32px; } #movetop { top: 0px; left: 50%; background-position: 0px 32px; } #moveleft { top: 50%; left: 0px; background-position: 32px 0px; } #moveright { top: 50%; right: 0px; background-position: 0px 0px; } #movedown { bottom: 0px; left: 50%; background-position: 32px 32px; } </pre> In your javascript, define the following functions: <pre> onMoveTop : function( evt ) { console.log( "onMoveTop" ); evt.preventDefault(); this.scrollmap.scroll( 0, 300 ); }, onMoveLeft : function( evt ) { console.log( "onMoveLeft" ); evt.preventDefault(); this.scrollmap.scroll( 300, 0 ); }, onMoveRight : function( evt ) { console.log( "onMoveRight" ); evt.preventDefault(); this.scrollmap.scroll( -300, 0 ); }, onMoveDown : function( evt ) { console.log( "onMoveDown" ); evt.preventDefault(); this.scrollmap.scroll( 0, -300 ); }, </pre> And connect onclick events on the arrows to these functions in your javascript setup <pre> dojo.connect( $('movetop'), 'onclick', this, 'onMoveTop' ); dojo.connect( $('moveleft'), 'onclick', this, 'onMoveLeft' ); dojo.connect( $('moveright'), 'onclick', this, 'onMoveRight' ); dojo.connect( $('movedown'), 'onclick', this, 'onMoveDown' ); </pre> == Enable scrollmap zone extension == This is optional, when there can be unused screen space under the scrollmap that a player might want to use. Add this in your .tpl after the scrollmap div (the matching css rules has already been defined): <pre> <div id="map_footer" class="whiteblock"> <a href="#" id="enlargedisplay">&darr;&nbsp;&nbsp;{LABEL_ENLARGE_DISPLAY}&nbsp;&nbsp;&darr;</a> </div> </pre> In your javascript, define the following function: <pre> onIncreaseDisplayHeight: function( evt ) { console.log( '$$$$ Event : onIncreaseDisplayHeight' ); evt.preventDefault(); var cur_h = toint( dojo.style( $('map_container'), 'height' ) ); dojo.style( $('map_container'), 'height', ( cur_h+300 ) + 'px' ); }, </pre> and connect them to the 'enlargedisplay' link in your setup: <pre> dojo.connect( $('enlargedisplay'), 'onclick', this, 'onIncreaseDisplayHeight' ); </pre> 2a5e97072af863315ae4bad3c5110f7b7a36fd68 781 780 2013-04-26T13:57:14Z Een 3 /* Enable scrollmap zone extension */ wikitext text/x-wiki Scrollmap is a BGA client side component to display an infinite game area. In some games, players are building the main game area with tiles or cards. Examples: * Carcassonne * Saboteur * Takenoko * Taluva * ... Of course this cause an additional difficulty for the adaptation, because we have to display an infinite game area into a finite space on the screen. This is where Scrollmap component can help you. == Scrollmap in action == If you want to see how Scrollmap looks like, please try "Saboteur" or "Takenoko" games on BGA, or watch a game in progress. In both games, you can see that there are arrow controls around the main game area, so that players can use them to scroll the view. You can also drag'n'drop the game area to scroll. == How to use Scrollmap == At first, don't forget to add "ebg/scrollmap" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/scrollmap" /// <==== HERE ], </pre> Then, declare a new variable in your class for the Scrollmap object: <pre> constructor: function(){ console.log('yourgame constructor'); // Scrollable area this.scrollmap = new ebg.scrollmap(); </pre> Now, open your template (TPL) file and add this HTML code: <pre> <div id="map_container"> <div id="map_scrollable"></div> <div id="map_surface"></div> <div id="map_scrollable_oversurface"></div> <a id="movetop" href="#"></a> <a id="moveleft" href="#"></a> <a id="moveright" href="#"></a> <a id="movedown" href="#"></a> </div> </pre> There are also some lines to add to your CSS stylesheet. Please note that you can adapt it to your needs, especially the default width of the scrollable area: <pre> /** Scrollable area **/ #map_container { position: relative; width: 100%; height: 400px; overflow: hidden; } #map_scrollable, #map_scrollable_oversurface { position: absolute; top: 205px; left: 315px; } #map_surface { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; cursor: move; } #map_footer { text-align: center; } </pre> Finally, to link your HTML code with your Javascript, place this in your Javascript "Setup" method: <pre> // Make map scrollable this.scrollmap.create( $('map_container'),$('map_scrollable'),$('map_surface'),$('map_scrollable_oversurface') ); this.scrollmap.setupOnScreenArrows( 150 ); </pre> This is it! Now, you should see on your game interface a scrollable game area. This is not really impressive though, because you didn't add anything on the game area yet. This is the next step. == Scrollable area layers == There are 2 - and only 2 - places where you should place your HTML stuff in your scrollable area: * inside "map_scrollable" div * inside "map_scrollable_oversurface" div The difference is very important: "map_scrollable" is beneath the surface that is used to drag'n'drop the game area, and "map_scrollable_oversurface" is above this surface. In practice: * If some element on the game area need to be clicked (or any kind of user interaction), you should place it in map_scrollable_oversurface, otherwise no click can reach it. * If some element on the game area don't need to be clicked, you'd better place it in "map_scrollable", so it is possible to drag'n'drop the game area from a point on this element. Of course, all layers are scrolled synchronously. Tips: in some situation, it's also useful to place a game element on map_scrollable and a corresponding invisible element over the surface to manage the interactions. Example: when an interactive element must be placed beneath a non interactive element for display reason. == Positioning elements on game area == All elements on the game are must be absolute positioned (with "top" and "left" attributes). By default, the game area is centered on 0,0 coordinates. == Enable move arrows == To show move arrows icons around the scrollmap in order to enable click based navigation in addition to drag and drop, add these lines to your CSS: <pre> /** Move arrows **/ #movetop,#moveleft,#moveright,#movedown { display: block; position: absolute; background-image: url('../../img/common/arrows.png'); width: 32px; height: 32px; } #movetop { top: 0px; left: 50%; background-position: 0px 32px; } #moveleft { top: 50%; left: 0px; background-position: 32px 0px; } #moveright { top: 50%; right: 0px; background-position: 0px 0px; } #movedown { bottom: 0px; left: 50%; background-position: 32px 32px; } </pre> In your javascript, define the following functions: <pre> onMoveTop : function( evt ) { console.log( "onMoveTop" ); evt.preventDefault(); this.scrollmap.scroll( 0, 300 ); }, onMoveLeft : function( evt ) { console.log( "onMoveLeft" ); evt.preventDefault(); this.scrollmap.scroll( 300, 0 ); }, onMoveRight : function( evt ) { console.log( "onMoveRight" ); evt.preventDefault(); this.scrollmap.scroll( -300, 0 ); }, onMoveDown : function( evt ) { console.log( "onMoveDown" ); evt.preventDefault(); this.scrollmap.scroll( 0, -300 ); }, </pre> And connect onclick events on the arrows to these functions in your javascript setup <pre> dojo.connect( $('movetop'), 'onclick', this, 'onMoveTop' ); dojo.connect( $('moveleft'), 'onclick', this, 'onMoveLeft' ); dojo.connect( $('moveright'), 'onclick', this, 'onMoveRight' ); dojo.connect( $('movedown'), 'onclick', this, 'onMoveDown' ); </pre> == Enable scrollmap zone extension == This is optional, when there can be unused screen space under the scrollmap that a player might want to use. Add this in your .tpl after the scrollmap div (the matching css rules has already been defined): <pre> <div id="map_footer" class="whiteblock"> <a href="#" id="enlargedisplay">&darr;&nbsp;&nbsp;{LABEL_ENLARGE_DISPLAY}&nbsp;&nbsp;&darr;</a> </div> </pre> In your javascript, define the following function: <pre> onIncreaseDisplayHeight: function( evt ) { console.log( '$$$$ Event : onIncreaseDisplayHeight' ); evt.preventDefault(); var cur_h = toint( dojo.style( $('map_container'), 'height' ) ); dojo.style( $('map_container'), 'height', ( cur_h+300 ) + 'px' ); }, </pre> and connect them to the 'enlargedisplay' link in your setup: <pre> dojo.connect( $('enlargedisplay'), 'onclick', this, 'onIncreaseDisplayHeight' ); </pre> In your view.php file, define the template variable LABEL_ENLARGE_DISPLAY so that it gets substituted with appropriate translatable text: <pre> $this->tpl['LABEL_ENLARGE_DISPLAY'] = self::_("Enlarge display"); </pre> 3589839894165d82db552742333c42b99f573a78 Zone 0 113 770 2013-04-20T17:16:41Z Een 3 Created page with "The Zone component is meant to organise items of the same type inside a predefined space. == Zone in action == If you want to see how Zone works, please try "Can't Stop" or ..." wikitext text/x-wiki The Zone component is meant to organise items of the same type inside a predefined space. == Zone in action == If you want to see how Zone works, please try "Can't Stop" or "Niagara" on BGA, or watch a game in progress or game replay. In Can't Stop, zone is used to display the bhikkus ascending the mountain when there is more than one on the same space (diagonal mode). In Niagara, it is used to display the canoes over the circles going down the river (custom mode). == How to use Zone == At first, don't forget to add "ebg/zone" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/zone" /// <==== HERE ], </pre> Then, declare a new variable in your class for the Zone object: <pre> constructor: function(){ console.log('yourgame constructor'); // Zone control this.myZone = new ebg.scrollmap(); </pre> Now, in your template file, you must add a div that will host this zone: <pre> <div id="my_zone"></div> </pre> And set its width (and optionnaly, height and position) in CSS: <pre> #my_zone { width: 100px; } </pre> Then in your Javascript setup, attach your Zone component to the div and define its properties : <pre> zone.create( this, 'my_zone', <item_width>, <item_height> ); zone.setPattern( <mode> ); </pre> * <item_width> is an integer for the width of the objects you want to organise in the zone * <item_height> is an integer for the height of the objects you want to organise in the zone * <mode> is one of 'grid' (objects will be put on lines from top left to bottom right, wrapping when there is not enough space left on the line) 'diagonal' (objects will be organised on a top left to bottom right diagonal, overlapping each other) or 'custom' (objects will be organised depending upon their number and the coordinates that you provide - see below) 3b1acb84955007d42770352ff5eaec3220ecff2f 771 770 2013-04-20T17:38:13Z Een 3 wikitext text/x-wiki The Zone component is meant to organise items of the same type inside a predefined space. == Zone in action == If you want to see how Zone works, please try "Can't Stop" or "Niagara" on BGA, or watch a game in progress or game replay. In Can't Stop, zone is used to display the bhikkus ascending the mountain when there is more than one on the same space (diagonal mode). In Niagara, it is used to display the canoes over the circles going down the river (custom mode). == How to use Zone == At first, don't forget to add "ebg/zone" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/zone" /// <==== HERE ], </pre> Then, declare a new variable in your class for the Zone object: <pre> constructor: function(){ console.log('yourgame constructor'); // Zone control this.myZone = new ebg.scrollmap(); </pre> Now, in your template file, you must add a div that will host this zone: <pre> <div id="my_zone"></div> </pre> And set its width (and optionnaly, height and position) in CSS: <pre> #my_zone { width: 100px; } </pre> Then in your Javascript setup, attach your Zone component to the div and define its properties : <pre> zone.create( this, 'my_zone', <item_width>, <item_height> ); zone.setPattern( <mode> ); </pre> * <item_width> is an integer for the width of the objects you want to organise in the zone * <item_height> is an integer for the height of the objects you want to organise in the zone * <mode> is one of 'grid' (objects will be put on lines from top left to bottom right, wrapping when there is not enough space left on the line) 'diagonal' (objects will be organised on a top left to bottom right diagonal, overlapping each other) or 'custom' (objects will be organised depending upon their number and the coordinates that you provide - see below) Now your zone is ready to be used! After creating an object that you want to add to the zone as a classic HTML template (dojo.place / this.format_block), you can simply use: <pre> zone.placeInZone( <object_id>, <weight> ); </pre> * <object_id> is the string identifier for your object 'my_object_id' * <weight> is an optional parameter used to sort items To remove an item, use: <pre> zone.removeFromZone( <object_id>, <destroy?>, <to> ); </pre> * <object_id> is the string identifier for your object 'my_object_id' * <destroy?> is a boolean indicating if the object should be destroyed after being removed * <to> is the destination the object must be slided to when being removed (before being eventually destroyed) You can also: * remove all items from the zone (and destroy them) using zone.removeAll(); * get the number of items in your zone using zone.getItemNumber(); * get an array of the ids of all the items using zone.getAllItems(); f3e8cbbc363d78eb8dcb46bf70ffb2710985f7bb 772 771 2013-04-20T17:42:40Z Een 3 wikitext text/x-wiki The Zone component is meant to organise items of the same type inside a predefined space. == Zone in action == If you want to see how Zone works, please try "Can't Stop" or "Niagara" on BGA, or watch a game in progress or game replay. In Can't Stop, zone is used to display the bhikkus ascending the mountain when there is more than one on the same space (diagonal mode). In Niagara, it is used to display the canoes over the circles going down the river (custom mode). == How to use Zone == At first, don't forget to add "ebg/zone" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/zone" /// <==== HERE ], </pre> Then, declare a new variable in your class for the Zone object: <pre> constructor: function(){ console.log('yourgame constructor'); // Zone control this.myZone = new ebg.scrollmap(); </pre> Now, in your template file, you must add a div that will host this zone: <pre> <div id="my_zone"></div> </pre> And set its width (and optionnaly, height and position) in CSS: <pre> #my_zone { width: 100px; } </pre> Then in your Javascript setup, attach your Zone component to the div and define its properties : <pre> zone.create( this, 'my_zone', <item_width>, <item_height> ); zone.setPattern( <mode> ); </pre> * <item_width> is an integer for the width of the objects you want to organise in the zone * <item_height> is an integer for the height of the objects you want to organise in the zone * <mode> is one of 'grid' (objects will be put on lines from top left to bottom right, wrapping when there is not enough space left on the line) 'diagonal' (objects will be organised on a top left to bottom right diagonal, overlapping each other) or 'custom' (objects will be organised depending upon their number and the coordinates that you provide - see below) Now your zone is ready to be used! After creating an object that you want to add to the zone as a classic HTML template (dojo.place / this.format_block), you can simply use: <pre> zone.placeInZone( <object_id>, <weight> ); </pre> * <object_id> is the string identifier for your object 'my_object_id' * <weight> is an optional parameter used to sort items To remove an item, use: <pre> zone.removeFromZone( <object_id>, <destroy?>, <to> ); </pre> * <object_id> is the string identifier for your object 'my_object_id' * <destroy?> is a boolean indicating if the object should be destroyed after being removed * <to> is the destination the object must be slided to when being removed (before being eventually destroyed) You can also: * remove all items from the zone (and destroy them) using zone.removeAll(); * get the number of items in your zone using zone.getItemNumber(); * get an array of the ids of all the items using zone.getAllItems(); == Custom mode == If you want complete control on how your objects are laid out inside the Zone, you can determine their coordinates after their number when being added to the zone. Here is how to do it, when defining your Zone properties in the javascript setup: <pre> this.zone.setPattern( 'custom' ); this.zone.itemIdToCoords = function( i, control_width ) { if( i%8==0 ) { return { x:1,y:19, w:60, h:30 }; } else if( i%8==1 ) { return { x:30,y:38, w:60, h:30 }; } else if( i%8==2 ) { return { x:42,y:8, w:60, h:30 }; } else if( i%8==3 ) { return { x:5,y:58, w:60, h:30 }; } else if( i%8==4 ) { return { x:5,y:24, w:60, h:30 }; } else if( i%8==5 ) { return { x:35,y:43, w:60, h:30 }; } else if( i%8==6 ) { return { x:47,y:13, w:60, h:30 }; } else if( i%8==7 ) { return { x:10,y:63, w:60, h:30 }; } }; </pre> afea6db99aa0caa0117e35848e3982a5cefa003e Kaozeadenn Implijer:Elisha 3 114 773 2013-04-21T20:36:30Z Elisha 2997 Camp Phillip wikitext text/x-wiki == Camp Phillip == It is in Wautoma 7a30187f839af147b50b8b04b297d320f6416207 Tools and tips of BGA Studio 0 99 774 724 2013-04-21T21:46:57Z Rudolf 2790 /* Run from the chat */ MoneyToPlayer instead ToCurrentPleyer wikitext text/x-wiki == Starting a game in one click == To start a game: * Create a new table with your game. * If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table. * Click on "Express Start". == Stopping a game in one click == * Click on the "quit" icon on the top right of the screen. * Click on "Express Stop". == Switching between users == when running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective. == Access to game database == Immediately at the bottom of the game area, the "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game. == Save & restore state == Using links of this section, you can save the complete current (database) state of your game, then restore it later. This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine. We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations. Limits: * the "restore" function does not work anymore when the game is over. * a saved situation from a given table cannot be restored in another table. * when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually. == Input/Output debugging section == This section shows you: * The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">" * The notifications received by your game interface. Notifications (inputs) begins with "<". Note: if you click on some notification title, you can resend it immediately to the user interface. == Run from the chat == On BGA Studio, you can directly run a PHP method from the chat. For example, if on your PHP you have this method: <pre> function giveMoneyToPlayer($player_id, $amount) { // Do some stuff } </pre> You can call this method directly from the chat like this: "giveMoneyToPlayer(2564,2)". == Dev Tips == '''Edit TPL''' <p> To edit TPL with HTML code highlightings in Gedit under Ubuntu: find gtksourceview directory in /usr/share, depending on your version (2.0, 3.0,...). <br> Here it's 3.0, then type in a terminal window: <pre> sudo gedit /usr/share/gtksourceview-3.0/language-specs/html.lang </pre> then find 'globs' section, and change: <pre> <property name="globs">*.html;*.htm;*.tpl</property> </pre> 7575406d5970f76c7920d09a72393b76aa7a139e How to join BGA developer team? 0 83 777 740 2013-04-24T20:19:05Z Een 3 ² wikitext text/x-wiki '''--- Notice ---''' We have received a lot of positive feedback on the Studio, and lots of developers have registered. We are very happy about it, but it comes with a cost in time spent answering emails and posts on the forum. So please bear with us if we are slow to answer. As soon as we can, we will. Thanks again for your interest! Registering is done by e-mail at '''studio(at)boardgamearena.com'''. Please provide the following information: * your player user name on BGA * your developer user name to be used on “BGA Studio” (for technical reasons, no space, number or special character); * your real name; * your e-mail address; * your postal address. We also drafted a quick [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf ''''terms & conditions' document''']. It's very light, so as to get to the fun part faster. To be valid, the registration e-mail must contain this document as an attachment, with the following sentence in the mail body: ''''I agree with the terms & conditions for developers on BGA Studio joined as an attachment''''. And of course, we also encourage you to tell us about your developer experience and which games you would love to develop on BGA! == Ok, I registered, what do I get? == First, we'll discuss by e-mail the names of some of the games we have an agreement to develop, so that you can tell us 'Hey, this game is great! I want to develop it!' (please keep these names confidential, or it would ruin our tradition to make players guess the name of the next game on the forum) Second, once we have discussed together and are set on a game you'll take charge of, we'll create your studio account and you will get: * one login / password to access files through SFTP * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. Once logged in to your SFTP root folder, you will find: * a ''''resources.html'''' file with the URLs to use and some extra connection information * three folders containing the three simple games provided as examples * a folder for the game you will be developing initialized after our 'EmptyGame' template, providing the game structure (and comments! and examples!) Then... well that's all, you can start! See [[Studio#Great.2C_I.27m_in.21_..._How_should_I_start.3F|Great, I'm in! ... How should I start?]] f33949896ce62ca89e3592d2b284019fa26aa725 Studio FAQ 0 53 778 582 2013-04-25T20:01:50Z Een 3 wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the [http://winscp.net/ WinSCP client]. == I can't edit the files in my game directory, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. Check [[Translations]] to see how to make your game translatable. == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Should I use images free from copyright? == If you are developing a game in the public domain, yes (or you can make your own if you feel it's better). If you are developing a game for which we have a licence, we will usually provide art files from the publisher. de2963afe15123299fc130eb797b6dec2336f852 779 778 2013-04-25T20:03:11Z Een 3 /* Should I use images free from copyright? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the [http://winscp.net/ WinSCP client]. == I can't edit the files in my game directory, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. Check [[Translations]] to see how to make your game translatable. == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == An extra deployment action from the BGA administrators is needed to activate new game options and statistics. Please contact us. == Should I use images free from copyright? == If you are developing a game in the public domain, yes (or you can make your own if you feel it's better). If you are developing a game for which we have a licence, we will usually provide art files from the publisher. 0a29445f5efe57020b3a57c7cd1dc368e323f8a7 Gamehelpjaipur 0 115 782 2013-04-28T02:32:04Z Coolpapa 3036 Rules summary added wikitext text/x-wiki In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take. On your turn, you take one of three actions: - "Take" a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn. - "Trade" for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards. - "Sell" cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded. The game continues until either: - Three piles of goods tokens are depleted, OR - The card row cannot be replenished. At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game. 961a44a284c0dcaf904d1e738bef062cb01b38a7 786 782 2013-04-28T22:47:55Z Zkiller 1253 wikitext text/x-wiki In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take. On your turn, you take one of three actions: - Take a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn. - Trade for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards. - Sell cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded. The game continues until either: - Three piles of goods tokens are depleted, OR - The card row cannot be replenished. At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game. e36707fc2bb42423ae195ad7e075bda6793b9811 787 786 2013-04-28T22:48:26Z Zkiller 1253 wikitext text/x-wiki In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take. On your turn, you take one of three actions: - Take a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn. - Trade for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards. - Sell cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded. The game continues until either: - Three piles of goods tokens are depleted, OR - The card row cannot be replenished. At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game. b784c03317aaeaa85595a08a0437840627e181f5 788 787 2013-04-28T22:48:54Z Zkiller 1253 wikitext text/x-wiki In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take. On your turn, you take one of three actions: - Take a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn. - Trade for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards. - Sell cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded. The game continues until either: - Three piles of goods tokens are depleted, OR - The card row cannot be replenished. At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game. afbf2081c76a32ae7bfaa6e3df778a7baa8af5a4 789 788 2013-04-28T22:49:12Z Zkiller 1253 wikitext text/x-wiki In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take. On your turn, you take one of three actions: - Take a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn. - Trade for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards. - Sell cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded. The game continues until either: - Three piles of goods tokens are depleted, OR - The card row cannot be replenished. At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game. cbe563e749c1ac4f0a52a3254a38d2a63809aa4f 790 789 2013-04-28T22:50:59Z Zkiller 1253 wikitext text/x-wiki <nowiki>In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take. On your turn, you take one of three actions: - Take a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn. - Trade for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards. - Sell cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded. The game continues until either: - Three piles of goods tokens are depleted, OR - The card row cannot be replenished. At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game.</nowiki> dccbdb4a9810a9fbf0a6ad10688939e8cc8c6141 791 790 2013-04-28T22:51:35Z Zkiller 1253 wikitext text/x-wiki In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take. On your turn, you take one of three actions: - Take a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn. - Trade for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards. - Sell cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded. The game continues until either: - Three piles of goods tokens are depleted, OR - The card row cannot be replenished. At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game. cbe563e749c1ac4f0a52a3254a38d2a63809aa4f 792 791 2013-04-28T22:53:13Z Zkiller 1253 wikitext text/x-wiki In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take. On your turn, you take one of three actions: 1. Take a single card or all the camels in the face up row: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) The card row is then replenished from the deck so it always has 5 cards at the start of a turn. 2. Trade for 2 or more goods cards from the row. You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. The cards your traded are added to the card row, so it will still have 5 cards. 3. Sell cards to earn points: You may sell one or more cards to earn points, but all the cards you sell must be the same color. If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). The sold goods cards are discarded. The game continues until either: Three piles of goods tokens are depleted, OR The card row cannot be replenished. At that point, players total the points they have on their earned goods tokens and bonus tokens. In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. Whichever player earns more points total wins the round. After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game. 4252f07fcba2193fdc6fca5d3eb71abba575b82f Gamehelpseasons 0 43 783 713 2013-04-28T08:34:30Z Tolcso 3039 wikitext text/x-wiki Season is a game of generating points (crystal) by choosing the correct combination of dice and the activation of card powers. The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be returned to the player on the starting of each cycle. Each player can choose only one die per turn. The effects are as follows: Star - increase the maximum card player can summon (max 15) Elements - Gain an energy of the element shown (water, earth, air, fire) Numbers - Gain the number of Crystals as indicated by the number Square card - Draw a card Dice with frames surrounding - Allow user to transmute energy into crystal (depend on which part of the game is at) Dots - Indicate how fast the marker progress through the seasons cycle There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There is 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice). At the end of the game the points are calculated by adding the numbers on each played card and the crystal owned and substracting 5 points for each power card remaining in hand. The player with the most victory points wins. Note: Users need to discard energy immediately if the energy is more than the slots allocated. If a card allows you to summon another card but you have no space for this second card then it (the second card) will be discarded with no refund. 3ea25e6e940596dbd22fb862bd8e668ff6747768 784 783 2013-04-28T08:47:52Z Tolcso 3039 wikitext text/x-wiki Season is a game of generating points (crystal) by choosing the correct combination of dice and the activation of card powers. The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be returned to the player on the starting of each cycle. Each player can choose only one die per turn. The effects are as follows: Star - increase the maximum card player can summon (max 15) Elements - Gain an energy of the element shown (water, earth, air, fire) Numbers - Gain the number of Crystals as indicated by the number Square card - Draw a card Dice with frames surrounding - Allow user to transmute energy into crystal (depend on which part of the game is at) Dots - Indicate how fast the marker progress through the seasons cycle There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There is 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice). At the end of the game the points are calculated by adding the numbers on each played card and the crystal owned and substracting 5 points for each power card remaining in hand. The player with the most victory points wins. Note: Users need to discard energy immediately if the energy is more than the slots allocated. If a card allows you to summon another card but you have no space for this second card then it (the second card) will be discarded with no refund. Difficulty levels: Apprentice wizard level In order to make the game easier to learn, there are “pre-constructed” sets of nine power cards. Instead of taking step 1 of the first game phase, each player gets one of these sets. Magician level Only the power cards numbered 1 to 30 are in play. These cards have easy to grasp effects and will allow you to slowly discover the world of Seasons. Archmage level All 50 kinds of power cards are in play. The cards numbered 31 through 50 have more complex effects than the basic cards, but will allow you to extend the fun of playing by discovering new effects and combinations. 7981328360c518298628e927fdde9a7e10945645 Gamehelpthermopyles 0 116 785 2013-04-28T18:45:18Z Boardgametravel 3042 Created page with "The rules for Thermopyles are on BoardGameTravel.com: http://boardgametravel.com/cardboard-sun-2013-thermopyles-by-touko-tahkokallio/" wikitext text/x-wiki The rules for Thermopyles are on BoardGameTravel.com: http://boardgametravel.com/cardboard-sun-2013-thermopyles-by-touko-tahkokallio/ 14db865c2a24bd8154124a531e44b068594fcc71 Steps to create a BGA game 0 117 794 2013-04-29T13:33:24Z Sourisdudesert 1 Created page with " Here's a summary of the different steps you would follow when developing a game with BGA Studio. {| class="wikitable" |- ! Step !! How to reach this ste?p !! What happened d..." wikitext text/x-wiki Here's a summary of the different steps you would follow when developing a game with BGA Studio. {| class="wikitable" |- ! Step !! How to reach this ste?p !! What happened during the step? |- | Initial || [[How to join BGA developer team?]] || You discuss with us to choose your game |- | Assigned || You choosed a game || You can start the development of the game |- | Pre-alpha || You've started to write some piece of code || You develop the game. During this phase, we can assist you with the framework and give you some pieces of advice. |- | Alpha || You tell us that your development is finished || We are reviewing the game on our side and with you, and help you to finalize some details to polish the game. |- | Private beta || We give a "go" || The game is incorporate in BGA global "package", and is published on BGA preproduction server. On this platform, the publisher, the designer, we and you can test the game together and separately. We help you to take into account remarks from the publisher and the designer. |- | Public beta || The adaptation is approved by the publiher || We find together a good launch date for the game, we announce the game on BGA news, and then player can start to play! During the first days, it is common that some bugs are reported by players, and you can fix them following the instructions in [[Post-release phase]]. |- | Gold || The game is stable on BGA || Congrats! You can still modify and optimize things following the instructions in [[Post-release phase]]. |} fd83647a0d63ee8c73d0d758a652a4fa882a89e9 Post-release phase 0 118 795 2013-04-29T13:55:59Z Sourisdudesert 1 Created page with " Your game is now on BGA: congrats! But what happened when there are some bugs to fix or when you want to optimize something? Don't be afraid: you're still allowed to modify..." wikitext text/x-wiki Your game is now on BGA: congrats! But what happened when there are some bugs to fix or when you want to optimize something? Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below. == BGA packages: when my updates will be visible by players? == BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package. It means that your updates won't be visible by players until a new package is build and released on the website. Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following: * We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs. * We can build another package: Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages. 00719bc33fbb31e5b9d0411273ca6934503dc879 796 795 2013-04-29T13:59:21Z Sourisdudesert 1 wikitext text/x-wiki Your game is now on BGA: congrats! But what happened when there are some bugs to fix or when you want to optimize something? Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below. == BGA packages: when my updates will be visible by players? == BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package. It means that your updates won't be visible by players until a new package is build and released on the website. Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following: * We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs. * We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :) Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game. You just have to inform us when you're ready to publish a new version. Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages. 3d6fce514ac532c20726ecc2298f198752a759a4 797 796 2013-04-29T14:02:35Z Sourisdudesert 1 wikitext text/x-wiki Your game is now on BGA: congrats! But what happened when there are some bugs to fix or when you want to optimize something? Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below. == BGA packages: when my updates will be visible by players? == BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package. It means that your updates won't be visible by players until a new package is build and released on the website. Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following: * We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs. * We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :) * If the situation is critical, we can suspend the game from BGA waiting for the update. Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version. Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages. == What can be modified after release? == Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases: ===Changes that breaks the games in progress=== Some changes will break the games in progress at the moment the release/the hotfix will be performed. 06912ed7642ce5075efe6e07129b9d6f7ef509e9 798 797 2013-04-29T14:09:13Z Sourisdudesert 1 /* What can be modified after release? */ wikitext text/x-wiki Your game is now on BGA: congrats! But what happened when there are some bugs to fix or when you want to optimize something? Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below. == BGA packages: when my updates will be visible by players? == BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package. It means that your updates won't be visible by players until a new package is build and released on the website. Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following: * We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs. * We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :) * If the situation is critical, we can suspend the game from BGA waiting for the update. Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version. Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages. == What can be modified after release? == Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases: ===Changes that breaks the games in progress=== Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us. Example of changes that break the games in progress: * Changes in the database schema of the game (dbmodel.sql). * New global variable or game option accessed during the game (if it's only used during setup, it should be safe). * New statistic (it won't be initialized properly, so it's going to crash the game). * Change ID of existing game states (adding new game states is fine). Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case: * Try to group all your updates in one BGA package, thus we won't have to block your game several times. * Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''. 1773893f8e863b61a600264dce70ad22267ac46c 799 798 2013-04-29T14:11:38Z Sourisdudesert 1 wikitext text/x-wiki Your game is now on BGA: congrats! But what happened when there are some bugs to fix or when you want to optimize something? Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below. == Bugs reporting == Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum]. During days after your game has been published and from time to time, please have a look at it to check if everything is fine. == BGA packages: when my updates will be visible by players? == BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package. It means that your updates won't be visible by players until a new package is build and released on the website. Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following: * We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs. * We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :) * If the situation is critical, we can suspend the game from BGA waiting for the update. Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version. Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages. == What can be modified after release? == Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases: ===Changes that breaks the games in progress=== Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us. Example of changes that break the games in progress: * Changes in the database schema of the game (dbmodel.sql). * New global variable or game option accessed during the game (if it's only used during setup, it should be safe). * New statistic (it won't be initialized properly, so it's going to crash the game). * Change ID of existing game states (adding new game states is fine). Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case: * Try to group all your updates in one BGA package, thus we won't have to block your game several times. * Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''. * Thus, during the package delivery, we will block the game and let game in progress end before publishing the new version. ===Major changes=== 700ca998e835f73a7be0541d4dc13a951a7c837e Post-release phase 0 118 800 799 2013-04-29T14:14:49Z Sourisdudesert 1 /* Major changes */ wikitext text/x-wiki Your game is now on BGA: congrats! But what happened when there are some bugs to fix or when you want to optimize something? Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below. == Bugs reporting == Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum]. During days after your game has been published and from time to time, please have a look at it to check if everything is fine. == BGA packages: when my updates will be visible by players? == BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package. It means that your updates won't be visible by players until a new package is build and released on the website. Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following: * We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs. * We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :) * If the situation is critical, we can suspend the game from BGA waiting for the update. Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version. Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages. == What can be modified after release? == Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases: ===Changes that breaks the games in progress=== Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us. Example of changes that break the games in progress: * Changes in the database schema of the game (dbmodel.sql). * New global variable or game option accessed during the game (if it's only used during setup, it should be safe). * New statistic (it won't be initialized properly, so it's going to crash the game). * Change ID of existing game states (adding new game states is fine). Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case: * Try to group all your updates in one BGA package, thus we won't have to block your game several times. * Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''. * Thus, during the package delivery, we will block the game and let game in progress end before publishing the new version. ===Major changes=== If you do some major changes to your game like: * Introducing a new expansion. * Major code rewriting/refactoring. ... please tell us. In this case, we can: * Make your game back from "gold" to "public beta", to incite player to report bugs. * Discuss with you about the release date of the next BGA package. * Pay attention to your game when publishing the package. * And eventually, publish a news about it :) 1e2c8a7c70f2e90310a06b99dbed1777b7587ac9 801 800 2013-05-02T12:01:04Z Sourisdudesert 1 /* BGA packages: when my updates will be visible by players? */ wikitext text/x-wiki Your game is now on BGA: congrats! But what happened when there are some bugs to fix or when you want to optimize something? Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below. == Bugs reporting == Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum]. During days after your game has been published and from time to time, please have a look at it to check if everything is fine. == How to submit changes? == To submit your changes, you just have to commit your work from BGA Studio backoffice, as you did during the development phase. Warning: as soon as you commited your changes, we assume that your code is ready to deploy '''anytime''' on BGA. Consequently, please do not commit a development in progress. == BGA packages: when my updates will be visible by players? == BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package. It means that your updates won't be visible by players until a new package is build and released on the website. Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following: * We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs. * We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :) * If the situation is critical, we can suspend the game from BGA waiting for the update. Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version. Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages. == What can be modified after release? == Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases: ===Changes that breaks the games in progress=== Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us. Example of changes that break the games in progress: * Changes in the database schema of the game (dbmodel.sql). * New global variable or game option accessed during the game (if it's only used during setup, it should be safe). * New statistic (it won't be initialized properly, so it's going to crash the game). * Change ID of existing game states (adding new game states is fine). Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case: * Try to group all your updates in one BGA package, thus we won't have to block your game several times. * Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''. * Thus, during the package delivery, we will block the game and let game in progress end before publishing the new version. ===Major changes=== If you do some major changes to your game like: * Introducing a new expansion. * Major code rewriting/refactoring. ... please tell us. In this case, we can: * Make your game back from "gold" to "public beta", to incite player to report bugs. * Discuss with you about the release date of the next BGA package. * Pay attention to your game when publishing the package. * And eventually, publish a news about it :) a894a30459e913bc4e1ea7a84648f20439ac5bef 802 801 2013-05-02T12:01:12Z Sourisdudesert 1 /* How to submit changes? */ wikitext text/x-wiki Your game is now on BGA: congrats! But what happened when there are some bugs to fix or when you want to optimize something? Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below. == Bugs reporting == Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum]. During days after your game has been published and from time to time, please have a look at it to check if everything is fine. == How to submit changes? == To submit your changes, you just have to commit your work from BGA Studio backoffice, as you did during the development phase. '''Warning''': as soon as you commited your changes, we assume that your code is ready to deploy '''anytime''' on BGA. Consequently, please do not commit a development in progress. == BGA packages: when my updates will be visible by players? == BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package. It means that your updates won't be visible by players until a new package is build and released on the website. Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following: * We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs. * We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :) * If the situation is critical, we can suspend the game from BGA waiting for the update. Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version. Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages. == What can be modified after release? == Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases: ===Changes that breaks the games in progress=== Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us. Example of changes that break the games in progress: * Changes in the database schema of the game (dbmodel.sql). * New global variable or game option accessed during the game (if it's only used during setup, it should be safe). * New statistic (it won't be initialized properly, so it's going to crash the game). * Change ID of existing game states (adding new game states is fine). Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case: * Try to group all your updates in one BGA package, thus we won't have to block your game several times. * Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''. * Thus, during the package delivery, we will block the game and let game in progress end before publishing the new version. ===Major changes=== If you do some major changes to your game like: * Introducing a new expansion. * Major code rewriting/refactoring. ... please tell us. In this case, we can: * Make your game back from "gold" to "public beta", to incite player to report bugs. * Discuss with you about the release date of the next BGA package. * Pay attention to your game when publishing the package. * And eventually, publish a news about it :) 3a40bfbd6133af2d943ac159671a956ff80bb408 803 802 2013-05-02T12:05:14Z Sourisdudesert 1 /* What can be modified after release? */ wikitext text/x-wiki Your game is now on BGA: congrats! But what happened when there are some bugs to fix or when you want to optimize something? Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below. == Bugs reporting == Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum]. During days after your game has been published and from time to time, please have a look at it to check if everything is fine. == How to submit changes? == To submit your changes, you just have to commit your work from BGA Studio backoffice, as you did during the development phase. '''Warning''': as soon as you commited your changes, we assume that your code is ready to deploy '''anytime''' on BGA. Consequently, please do not commit a development in progress. == BGA packages: when my updates will be visible by players? == BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package. It means that your updates won't be visible by players until a new package is build and released on the website. Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following: * We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs. * We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :) * If the situation is critical, we can suspend the game from BGA waiting for the update. Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version. Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages. == What can be modified after release? == Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases: ===Changes that breaks the games in progress=== Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us. Example of changes that break the games in progress: * Changes in the database schema of the game (dbmodel.sql). * New global variable or game option accessed during the game (if it's only used during setup, it should be safe). * New statistic (it won't be initialized properly, so it's going to crash the game). * Change ID of existing game states (adding new game states is fine). Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case: * Try to group all your updates in one BGA package, thus we won't have to block your game several times. * Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''. * Thus, during the package delivery, we will block the game and let game in progress end before publishing the new version. ===Major changes=== If you do some major changes to your game like: * Introducing a new expansion. * Major code rewriting/refactoring. ... please tell us. In this case, we can: * Make your game back from "gold" to "public beta", to incite player to report bugs. * Discuss with you about the release date of the next BGA package. * Pay attention to your game when publishing the package. * And eventually, publish a news about it :) ===Post-release and commit=== As said above: for games already published on BGA, we assume that your code is ready to deploy as soon as you commited your changes. In consequence, please: * Do not commit until you finished and tested your updates. * Do not commit a development in progress. * As a rule of thumb: do not commit something that will bring the game in a state that should not be seen by players. cdf42364d5f044ab669cc89ed65e8b7284dfffd0 824 803 2013-05-13T12:18:44Z Sourisdudesert 1 /* Changes that breaks the games in progress */ wikitext text/x-wiki Your game is now on BGA: congrats! But what happened when there are some bugs to fix or when you want to optimize something? Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below. == Bugs reporting == Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum]. During days after your game has been published and from time to time, please have a look at it to check if everything is fine. == How to submit changes? == To submit your changes, you just have to commit your work from BGA Studio backoffice, as you did during the development phase. '''Warning''': as soon as you commited your changes, we assume that your code is ready to deploy '''anytime''' on BGA. Consequently, please do not commit a development in progress. == BGA packages: when my updates will be visible by players? == BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package. It means that your updates won't be visible by players until a new package is build and released on the website. Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following: * We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs. * We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :) * If the situation is critical, we can suspend the game from BGA waiting for the update. Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version. Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages. == What can be modified after release? == Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases: ===Changes that breaks the games in progress=== Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us. Example of changes that break the games in progress: * Changes in the database schema of the game (dbmodel.sql). * New global variable or game option accessed during the game (if it's only used during setup, it should be safe). * New statistic (it won't be initialized properly, so it's going to crash the game). * Change ID of existing game states (adding new game states is fine). Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case: * Try to group all your updates in one BGA package, thus we won't have to block your game several times. * Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''. * Thus, during the package delivery, we will block the game and let game in progress end before publishing the new version. === Updating Statistics === You should be careful when updating a statistics: * If you want to add a new statistics, please refer to the paragraph above ("changes that breaks the games in progress"). * If you want to update a statistic, please update it and do not remove/create another one. Otherwise, the statistic won't keep the same ID and players will lost all the historical statistics data. * If your game is published on BGA, please don't remove any statistics (historical data will be lost). === Updating string to translate === When you update a string that has been marked to be translatable, please keep in mind that all current translations done by the BGA community will be lost. Consequently, when you are about to modify a string to be translated (after release), please ask you the following questions: * Is it just an English mispelling? In this case, it is better to fix the English translation of the string than the original string to be translated. ===Major changes=== If you do some major changes to your game like: * Introducing a new expansion. * Major code rewriting/refactoring. ... please tell us. In this case, we can: * Make your game back from "gold" to "public beta", to incite player to report bugs. * Discuss with you about the release date of the next BGA package. * Pay attention to your game when publishing the package. * And eventually, publish a news about it :) ===Post-release and commit=== As said above: for games already published on BGA, we assume that your code is ready to deploy as soon as you commited your changes. In consequence, please: * Do not commit until you finished and tested your updates. * Do not commit a development in progress. * As a rule of thumb: do not commit something that will bring the game in a state that should not be seen by players. 6e886bcf9df1b7d39c3fbacf9c439f64bb7126b7 825 824 2013-05-13T12:21:13Z Sourisdudesert 1 /* Updating string to translate */ wikitext text/x-wiki Your game is now on BGA: congrats! But what happened when there are some bugs to fix or when you want to optimize something? Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below. == Bugs reporting == Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum]. During days after your game has been published and from time to time, please have a look at it to check if everything is fine. == How to submit changes? == To submit your changes, you just have to commit your work from BGA Studio backoffice, as you did during the development phase. '''Warning''': as soon as you commited your changes, we assume that your code is ready to deploy '''anytime''' on BGA. Consequently, please do not commit a development in progress. == BGA packages: when my updates will be visible by players? == BGA website is updated with "packages". When needed, we build a new package with all games and release a new version of BGA with this package. It means that your updates won't be visible by players until a new package is build and released on the website. Usually, there is less than 2 weeks between 2 packages, so it's quick. BUT, if you detect some major bug in your game, please warn us immediately so we can decide what to do. Usually, we do the following: * We can do a "hotfix": you send us a very little change and we fix the website immediately. This is only possible if you change only the PHP side. The good news is that most blocking bugs are on PHP side - the client side bugs are most of the time solved by a page refresh. Of course, we don't hotfix minor bugs. * We can build another package. Of course, it's better to fix several bugs in each package, in order we don't have to build another package right after the first one :) * If the situation is critical, we can suspend the game from BGA waiting for the update. Of course, we particularly care of your game during the days after your game is available on BGA. During this period of time, there's no problem to build package and to hotfix just for your game, and this is done in close collaboration with you. You just have to inform us when you're ready to publish a new version. Note: don't forget that in any case, you need to commit your changes to made them available for the next package. Modifications that are not commited are not included in the packages. == What can be modified after release? == Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases: ===Changes that breaks the games in progress=== Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us. Example of changes that break the games in progress: * Changes in the database schema of the game (dbmodel.sql). * New global variable or game option accessed during the game (if it's only used during setup, it should be safe). * New statistic (it won't be initialized properly, so it's going to crash the game). * Change ID of existing game states (adding new game states is fine). Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case: * Try to group all your updates in one BGA package, thus we won't have to block your game several times. * Tell us explicitly that you introduce some update that can break games in progress, '''as soon as you commit your update'''. * Thus, during the package delivery, we will block the game and let game in progress end before publishing the new version. === Updating Statistics === You should be careful when updating a statistics: * If you want to add a new statistics, please refer to the paragraph above ("changes that breaks the games in progress"). * If you want to update a statistic, please update it and do not remove/create another one. Otherwise, the statistic won't keep the same ID and players will lost all the historical statistics data. * If your game is published on BGA, please don't remove any statistics (historical data will be lost). === Updating string to be translated === When you update a string that has been marked to be translatable, please keep in mind that all current translations done by the BGA community will be lost. Consequently, when you are about to modify a string to be translated (after release), please ask you the following questions: * Is it just an English misspelling? In this case, it is better to fix the English translation of the string than the original string to be translated. * Has the meaning of the string changed? If yes, you HAVE to change the original string in order to invalidate all translations that has been done already. * Is there a similar string already used elsewhere in my game? In this case, you'd better use it again to enjoy immediately all translations already available. ===Major changes=== If you do some major changes to your game like: * Introducing a new expansion. * Major code rewriting/refactoring. ... please tell us. In this case, we can: * Make your game back from "gold" to "public beta", to incite player to report bugs. * Discuss with you about the release date of the next BGA package. * Pay attention to your game when publishing the package. * And eventually, publish a news about it :) ===Post-release and commit=== As said above: for games already published on BGA, we assume that your code is ready to deploy as soon as you commited your changes. In consequence, please: * Do not commit until you finished and tested your updates. * Do not commit a development in progress. * As a rule of thumb: do not commit something that will bring the game in a state that should not be seen by players. 356393196feb99d952606ceadf545a08b97dfa02 Your game state machine: states.inc.php 0 90 804 729 2013-05-05T21:14:19Z Rudolf 2790 /* args */ argPlayerTurn instead argPlaceWorker :) wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "args" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> === args === (optional) From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state. Example 1 : for Reversi, the list of possible moves during playerTurn state. Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor. Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them. In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them. Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array. Let's see a complete example using args with « Reversi » game : In states.inc.php, we specify some « args » argument for gamestate « playerTurn » : <pre> 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", <================================== HERE "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), </pre> It corresponds to a « argPlayerTurn » method in our PHP code (reversi.game.php): <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves() ); } </pre> Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn : <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> Note: you can also used values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above). Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn). === updateGameProgression === (optional) IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated. At least one of your game state (any of them) must specify updateGameProgression=>true. 3812e44b110471e5e6b8940d1dd683d52a7c7946 Studio function reference 0 55 805 448 2013-05-06T17:07:55Z Sourisdudesert 1 /* Client side (Javascript functions) */ wikitext text/x-wiki This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to). This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below. == Server side (PHP functions) == == Client side (Javascript functions) == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : DEPRECATED (see connectClass below) ; connectClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player e95dad6f948fc435abb59e380167b6a3cabc6080 806 805 2013-05-06T17:08:23Z Sourisdudesert 1 /* Client side (Javascript functions) */ wikitext text/x-wiki This page references useful server side and client side functions (and some interesting class variables), so that nobody needs to reinvent the wheel (unless he wants to). This list is not exhaustive, in particular functions already well described by comments in the 'EmptyGame' game template may not be described again below. == Server side (PHP functions) == == Client side (Javascript functions) == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side. ; slideToObject: function( mobile_obj, target_obj, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one : Animate a slide of the DOM object referred to by domNodeToSlide from its current position to the xpos, ypos relative to the object referred to by domNodeToSlideTo. ; slideToObjectPos: function( mobile_obj, target_obj, target_x, target_y, duration, delay ) : Return an dojo.fx animation that is sliding a DOM object from its current position over another one at the given coordinates relative to the target object. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. ; addTooltip( node, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to the DOM node. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. ; addTooltipHtml( node, html, delay ); : Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). ; addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay ); : Add a simple text tooltip to all the DOM nodes set with this cssClass. Only one of 'helpString' or 'actionString' must be used. _() must be used for the text to be marked for translation. : NB: all concerned nodes must have IDs to get tooltips ; addTooltipHtmlToClass( cssClass, html, delay ); : Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). : NB: all concerned nodes must have IDs to get tooltips ; addEventToClass: function( cssClassName, eventName, functionName ) : DEPRECATED (please use connectClass below) ; connectClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName ; addStyleToClass: function( cssClassName, cssProperty, propertyValue ) : Same as dojo.style(), but for all the nodes set with the specified cssClassName ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; checkAction: function( action, nomessage ) : Check if player can do the specified action by taking into account: _ current game state & _ interface locking : return true if action is authorized : return false and display an error message if not (display no message if nomessage is specified) ; showMessage: function( msg, type ) : Show an information message during a few seconds at the top of the page : Type can be 'error' or 'info' ; this.scoreCtrl[ player_id ].incValue( score_delta ); : Adds score_delta (positive or negative integer) to the current score value for player 160e684dfe21df32501ea756dd20aa6dad8f0b36 Gamehelpniagara 0 119 807 2013-05-08T10:38:45Z Drstuey 3099 Created page with "Players paddle canoes along the Niagara river to collect gems of five different colors and bring them safely back to shore without being swept over the waterfall. To win, a pl..." wikitext text/x-wiki Players paddle canoes along the Niagara river to collect gems of five different colors and bring them safely back to shore without being swept over the waterfall. To win, a player must return either: * five different colored gems * four gems of the same color * seven gems of any color The tie break is the value of the gems - the gems closer to the waterfall have a higher value. In order the gems are: : Gem - Color - Value : Amethyst - Violet - 1 : Diamond - Clear - 2 : Amber - Yellow - 3 : Sapphire - Blue - 4 : Ruby - Pink - 5 Players have a set of 7 paddle cards which they play to determine the speed of their canoes and the speed of the river. 4ff0d66fb1e334b75f2b1d160b47252872bad10c 808 807 2013-05-08T10:44:52Z Drstuey 3099 wikitext text/x-wiki Players paddle canoes along the Niagara river to collect gems of five different colors and bring them safely back to shore without being swept over the waterfall. To win, a player must return either: * five different colored gems * four gems of the same color * seven gems of any color The tie break is the value of the gems - the gems closer to the waterfall have a higher value. In order the gems are: : Gem - Color - Value : Amethyst - Violet - 1 : Diamond - Clear - 2 : Amber - Yellow - 3 : Sapphire - Blue - 4 : Ruby - Pink - 5 Players have a set of 7 paddle cards which they play to determine the speed of their canoes and the speed of the river. All players must select the card they will play before the players then move their canoes in turn order. Once a card has been played it is not available to play again until all 7 cards have been played. 572aa6c5a9b8af31652c9722ecc4b01d8201d376 839 808 2013-05-26T07:59:53Z Drstuey 3099 wikitext text/x-wiki Players paddle canoes along the Niagara river to collect gems of five different colors and bring them safely back to shore without being swept over the waterfall. To win, a player must return either: * five different colored gems * four gems of the same color * seven gems of any color The tie break is the value of the gems - the gems closer to the waterfall have a higher value. In order the gems are: : Gem - Color - Value : Amethyst - Violet - 1 : Diamond - Clear - 2 : Amber - Yellow - 3 : Sapphire - Blue - 4 : Ruby - Pink - 5 Players have a set of 7 paddle cards which they play to determine the speed of their canoes and the speed of the river. All players must select the card they will play before the players then move their canoes in turn order. Once a card has been played it is not available to play again until all 7 cards have been played. After all the players have moved their canoes the river moves causing all the canoes on the river to be swept downstream. The river moves the same number of places as the lowest value paddle card played plus or minus a modifier depending on the weather. At the beginning of the game the weather is set to 0 so there is no modification but each player also has a cloud card as part of their set of paddle cards that allows them to adjust the weather and hence make the river speed up or slow down. The number on the paddle card determines the number of spaces that the canoe moves - it costs 2 paddle points to pick up (or offload) a gem. Thus if a player chose their 5 card they could move their canoe 5 spaces *or* they could move their canoe 3 spaces and pick up a gem (or they could offload a gem and move their canoe 3 spaces). Both canoes may be moved with the same paddle card - both canoes are moved the same amount, the paddles points are not split between the canoes. When both canoes are out of the water only one can be launched in that turn. If both canoes are in the water they must both be moved using the full value of the paddle points - a player cannot chose not to move one canoe and must always use the full value of the paddle points. However if one of the canoes is out of the water a player may choose not to launch it. Canoes may only move upstream or downstream in a single turn - it is not permitted to change direction in the middle of the turn. However one canoe could move upstream and the second one downstream. Players may steal gems from other canoes, but only after moving upstream and only if they finish on the same space as the other player (and only if they have an empty canoes and hence space to load the gem). Turn order is therefore crucial for stealing. 11578909bb91ae614ac1f3ad026c9b251bda1aa5 Steps to create a BGA game 0 117 809 794 2013-05-09T18:54:43Z Sourisdudesert 1 wikitext text/x-wiki Here's a summary of the different steps you would follow when developing a game with BGA Studio. {| class="wikitable" |- ! Step !! How to reach this ste?p !! What happened during the step? |- | Initial || [[How to join BGA developer team?]] || You discuss with us to choose your game |- | Assigned || You choosed a game || You can start the development of the game |- | Pre-alpha || You've started to write some piece of code || You develop the game. During this phase, we can assist you with the framework and give you some pieces of advice. |- | Alpha || You tell us that your development is finished || The game is incorporate in BGA global "package", and is published on BGA preproduction server. We are reviewing the game on our side and with you, and help you to finalize some details to polish the game. |- | Private beta || We give a "go" || On preproduction platform, the publisher, the designer, we and you can test the game together and separately. We help you to take into account remarks from the publisher and the designer. |- | Public beta || The adaptation is approved by the publiher || We find together a good launch date for the game, we announce the game on BGA news, and then player can start to play! During the first days, it is common that some bugs are reported by players, and you can fix them following the instructions in [[Post-release phase]]. |- | Gold || The game is stable on BGA || Congrats! You can still modify and optimize things following the instructions in [[Post-release phase]]. |} 7ec2dce7dd3162238a0135745a42c2144a65ca5b Translations 0 94 810 675 2013-05-10T19:54:03Z Een 3 /* On client side (Javascript) */ wikitext text/x-wiki Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them. == How translation works? == When developing your game, all strings must be in English. Strings must be coherent with the English version of the game. Before the release of the game, BGA team will do the French translation of the game. After the release of the game, the BGA players community will translate the game in every language. == What should be translated? == Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ... This does NOT include error messages that are not supposed to happened (unexpected errors). == Focus on translating notifications == Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function. However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side. == WARNING: how to make sure your strings will be translated == For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers). If your original string is not "physically" inside one of this marker, it won't be translated. <pre> // Examples: the following strings will be translated: var mystring_translated = _("my string"); // JS $mystring_translated = self::_("my string"); // PHP $mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP // Examples: the following strings WILL NOT be translated: $my_string = "my string"; $not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation $not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing </pre> == How to not make translators crazy ;) == * When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings. * Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it). * Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like: <pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre> Write instead: <pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre> (or the equivalent "dojo.string.substitute" in Javascript) * When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings. * The BGA translation policy is to be flexible on grammar... We prefer to write "player gets 1 coin(s)" than write two versions of the same string for plural and singular - it reduces the number of strings to translate. * Instead of writing nice strings like "With the effect of ZZZ, player XXX gets a new YYY", which is very difficult to translate, write strings like "ZZZ: XXX gets YYY". == On client side (Javascript) == On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate. Examples: <pre> // Get a string in player's language: var translated = _("original english string"); // Get a string in player's language with parameter: var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", { p: 2, d: 4 } ); </pre> '''WARNING:''' in Javascript strings to translate, you should never use '\n', '\t' or such, as it will break the translation bundle and result in all the Javascript translation to fail. In any case, the strings will result in HTML code, and such character codes won't have any impact on the HTML rendering. You should use HTML markup instead. == On server side (PHP) == On PHP side, you can use 3 different functions to specify that a string must be translated. '''clienttranslate( "my string to translate" ):''' This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side. In general, you use clienttranslate: * On your states.inc.php, for field "description" and "descriptionmyturn". <pre> "description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'), </pre> * On "material.inc.php", when defining texts for game material that must be displayed on client side. <pre> $this->card_types = array( 1 => array( 'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side. </pre> * When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation. <pre> // A game log string with no argument: self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() ); </pre> Translating arguments is a little bit more complex. It is using the "i18n" special argument as below: <pre> // In the following example, we translate the game log itself, but also the "card_name" argument: self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array( 'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'points' => $points, 'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string. ) ); </pre> '''self::_( "my string to translate" ):''' This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player). Most of the time, you don't need to translate strings on server side, except on the following 3 situations: * When throwing an exception because the player did a forbidden move. <pre> // This will display a translatable red message to the player that just do some wrong action: throw new feException( self::_('You must choose 3 cards'), true); // ... notice the use of "true" parameter that signal that this exception is "expected". In theory, all exception that are excepted should be translated. </pre> * In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file. <pre> $this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II"); </pre> * Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions. <pre> // In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this: throw new feException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'], true ); </pre> * Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user. '''totranslate( "my string to translate" ):''' This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side. You should not use this function, except on the following cases: * Statistics name in stats.inc.php * Option names and option values name in gameoptions.inc.php 22624734ef6e061272e85bfa5c3a50f5129dd586 836 810 2013-05-21T21:36:02Z Tilalilalou 2792 /* On server side (PHP) */ wikitext text/x-wiki Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them. == How translation works? == When developing your game, all strings must be in English. Strings must be coherent with the English version of the game. Before the release of the game, BGA team will do the French translation of the game. After the release of the game, the BGA players community will translate the game in every language. == What should be translated? == Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ... This does NOT include error messages that are not supposed to happened (unexpected errors). == Focus on translating notifications == Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function. However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side. == WARNING: how to make sure your strings will be translated == For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers). If your original string is not "physically" inside one of this marker, it won't be translated. <pre> // Examples: the following strings will be translated: var mystring_translated = _("my string"); // JS $mystring_translated = self::_("my string"); // PHP $mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP // Examples: the following strings WILL NOT be translated: $my_string = "my string"; $not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation $not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing </pre> == How to not make translators crazy ;) == * When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings. * Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it). * Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like: <pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre> Write instead: <pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre> (or the equivalent "dojo.string.substitute" in Javascript) * When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings. * The BGA translation policy is to be flexible on grammar... We prefer to write "player gets 1 coin(s)" than write two versions of the same string for plural and singular - it reduces the number of strings to translate. * Instead of writing nice strings like "With the effect of ZZZ, player XXX gets a new YYY", which is very difficult to translate, write strings like "ZZZ: XXX gets YYY". == On client side (Javascript) == On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate. Examples: <pre> // Get a string in player's language: var translated = _("original english string"); // Get a string in player's language with parameter: var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", { p: 2, d: 4 } ); </pre> '''WARNING:''' in Javascript strings to translate, you should never use '\n', '\t' or such, as it will break the translation bundle and result in all the Javascript translation to fail. In any case, the strings will result in HTML code, and such character codes won't have any impact on the HTML rendering. You should use HTML markup instead. == On server side (PHP) == On PHP side, you can use 3 different functions to specify that a string must be translated. '''clienttranslate( "my string to translate" ):''' This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side. In general, you use clienttranslate: * On your states.inc.php, for field "description" and "descriptionmyturn". <pre> "description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'), </pre> * On "material.inc.php", when defining texts for game material that must be displayed on client side. <pre> $this->card_types = array( 1 => array( 'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side. </pre> * When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation. <pre> // A game log string with no argument: self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() ); </pre> Translating arguments is a little bit more complex. It is using the "i18n" special argument as below: <pre> // In the following example, we translate the game log itself, but also the "card_name" argument: self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array( 'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'points' => $points, 'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string. ) ); </pre> '''self::_( "my string to translate" ):''' This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player). Most of the time, you don't need to translate strings on server side, except on the following 3 situations: * When throwing an exception because the player did a forbidden move. <pre> // This will display a translatable red message to the player that just do some wrong action: throw new BgaUserException( self::_('You must choose 3 cards') ); // ... notice the use of BgaUserException that signals that this exception is "expected". In theory, all exception that are expected should be translated. </pre> * In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file. <pre> $this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II"); </pre> * Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions. <pre> // In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this: throw new BgaUserException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'] ); </pre> * Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user. '''totranslate( "my string to translate" ):''' This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side. You should not use this function, except on the following cases: * Statistics name in stats.inc.php * Option names and option values name in gameoptions.inc.php febee0f3048f5cfd727355754ea4e0137867df32 Gamehelpdragonheart 0 31 811 146 2013-05-11T23:04:14Z Sternenfee83 3127 /* Cards */ wikitext text/x-wiki ==Summary== Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down. ==Goal== To have the most points by the end of the game. ==Game Start== At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board. ==End== The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 3 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game. In case of a tie, the player with the Great Dragon wins. ==Turns== Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship. ==Cards== There are nine types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it is. Arrows on the board indicate what cards can take what. * ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf. * ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board. * ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards. * ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress. * ''Troll'': Placing this card allows the player to take the sorceress pile. * ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board. * ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent. * ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon. * ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the deck. The ship cards are then discarded. The third time that three ship cards are played ends the game and the opponent takes one final turn. * ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand. 550055d41a907bf6a87ac1a5a0c8521d91f520f9 Gamehelpgearnpiston 0 112 812 776 2013-05-12T03:16:10Z Jirikki 2655 /* REQUIREMENTS OF A COMPLETE AUTOMOBILE */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Plan actions. *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (steal a part from another player), **or Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack. *Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Junk Parts stack. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank. * Colored improvements require an engine of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. ====SCORING==== * VP according to Investors * +1 VP for each part in one largest continuous area * -1 VP for each point of Volatility ====BEGINNER TIPS==== * Keep an eye on what other players are doing. * Make sure to build often enough so you don't end up with a full hand and unspent actions. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. * Reading the actual rules helps also. d635ec38db2d845cad6db71b86daa4af043eacba 813 812 2013-05-12T03:27:28Z Jirikki 2655 /* GAME END */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Plan actions. *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (steal a part from another player), **or Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack. *Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Junk Parts stack. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank. * Colored improvements require an engine of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors * +1 VP for each part in one largest continuous area * -1 VP for each point of Volatility ====BEGINNER TIPS==== * Keep an eye on what other players are doing. * Make sure to build often enough so you don't end up with a full hand and unspent actions. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. * Reading the actual rules helps also. de7e7b26782be0047213175f41810b1b0377928a 814 813 2013-05-12T03:41:47Z Jirikki 2655 /* SCORING */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Plan actions. *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (steal a part from another player), **or Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack. *Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Junk Parts stack. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank. * Colored improvements require an engine of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two of each are worth either 1, 2 or 3 based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. * Make sure to build often enough so you don't end up with a full hand and unspent actions. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. * Reading the actual rules helps also. 847321eb680103116893e558e7ce2f0a3ed8c89e 815 814 2013-05-12T03:48:02Z Jirikki 2655 /* ROUND SEQUENCE AND PHASES */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (steal a part from another player), **or Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack. *Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Junk Parts stack. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank. * Colored improvements require an engine of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two of each are worth either 1, 2 or 3 based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. * Make sure to build often enough so you don't end up with a full hand and unspent actions. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. * Reading the actual rules helps also. 8fe5b6392bbbcfaf3f233a60ad6a0113dd062127 816 815 2013-05-12T03:49:44Z Jirikki 2655 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (look at one player's blueprints and take one of them), **Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack. *Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Junk Parts stack. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank. * Colored improvements require an engine of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two of each are worth either 1, 2 or 3 based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. * Make sure to build often enough so you don't end up with a full hand and unspent actions. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. * Reading the actual rules helps also. 8546ba6ce30fb1fa8df1d50a9f6b5cc6ad76e451 817 816 2013-05-12T03:55:30Z Jirikki 2655 /* SCORING */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (look at one player's blueprints and take one of them), **Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the parts next to the game or from the New Parts stack. *Junk Yard: Take up to 2 Junk Parts, either from the parts next to the game or from the New Junk Parts stack. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank. * Colored improvements require an engine of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. * Make sure to build often enough so you don't end up with a full hand and unspent actions. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. * Reading the actual rules helps also. 9fc3e1b36e15b47dae5af304be9c4209c53f62e1 818 817 2013-05-12T04:04:02Z Jirikki 2655 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (look at one player's blueprints and take one of them), **Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the face up parts or from the top of the stack. *Junk Yard: Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank. * Colored improvements require an engine of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. * Make sure to build often enough so you don't end up with a full hand and unspent actions. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. * Reading the actual rules helps also. 99947660d1dd9a476d1e853fcf5db23ae7914722 819 818 2013-05-12T04:26:14Z Jirikki 2655 /* BEGINNER TIPS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (look at one player's blueprints and take one of them), **Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the face up parts or from the top of the stack. *Junk Yard: Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (motor and fuel tank), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank. * Colored improvements require an engine of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. c24c871220e1a21fa8a444d63e17d584192eb61a 820 819 2013-05-12T04:29:04Z Jirikki 2655 /* REQUIREMENTS OF A COMPLETE AUTOMOBILE */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (look at one player's blueprints and take one of them), **Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the face up parts or from the top of the stack. *Junk Yard: Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (a motor and at least one fuel tank of the same color), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements require an engine of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 900b2c3d01813d95f9b661bee2133ac6c411da5d 821 820 2013-05-12T04:33:08Z Jirikki 2655 /* REQUIREMENTS OF A COMPLETE AUTOMOBILE */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (look at one player's blueprints and take one of them), **Union Muscle (move Action Token ahead or behind in a location). *Patent Office: Take 1 New Part, either from the face up parts or from the top of the stack. *Junk Yard: Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (a motor and at least one fuel tank of the same color), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 8941f1d92c3e211c3ee931038e0e8f7762e2cff5 822 821 2013-05-12T04:36:44Z Jirikki 2655 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players, and is [http://www.kickstarter.com/projects/ludicreations/gear-and-piston-board-game now on Kickstarter]. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (look at one player's blueprints and take one of them), **Union Muscle (move an Action Token ahead in another location). *Patent Office: Take 1 New Part, either from the face up parts or from the top of the stack. *Junk Yard: Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (a motor and at least one fuel tank of the same color), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 96babae1589a1d46b75e44846654f7ff78eb3124 Kaozeal:Gamehelpgearnpiston 1 120 823 2013-05-12T04:39:59Z Jirikki 2655 Created page with "When using union muscle, are you swapping your token with another or are you sliding all the other tokens down when you move. Is there any reason to move your token down unles..." wikitext text/x-wiki When using union muscle, are you swapping your token with another or are you sliding all the other tokens down when you move. Is there any reason to move your token down unless you are trying to throw the game to another player? f863575cf8f5ead7a658701c4c549caeadd532e0 Gamehelpnorthwestpassage 0 121 826 2013-05-13T16:48:33Z Tirix 1962 Early version wikitext text/x-wiki '''''Looking for the Franklin Expedition''''' ''In 1845, Sir John Franklin led an expedition on behalf of the British Royal Navy to find and explore the last portion of the Northwest Passage. They sailed into unknown waters, and no-one ever heard from them again... Players must venture into these hazardous Arctic waters in order to discover Franklin’s fate and succeed where he failed: by finding the Northwest Passage.'' ---- In the game, prestige is awarded for exploring islands and straits, getting information from Inuits or Cairns about the Franklin Expedition, finding shipwrecks of the expedition, and for being among the first to find their way up to the Northwest Passage and back to Groenland. The player with the most Prestige points at the end of the game is the winner. In case of a tie, the first tied player to have returned to Greenland is the winner. == GAME CYCLE == The game is divided into ten rounds. At the end of each round, the solar disc moves, and part of the board above the sun freezes into ice or melts back to sea. During one round, player will take up to 7 actions, in turn. Actions can be taken either from the ship, using crewmen on the ship, or from the sled, using crewmen on the sled. On the player board, :Ship: 1/2 - Sled: 3/5 means for example that there are two crewmen on the ship and five on the sled, and that one crewman is available (out of two) on the ship, and three crewmen (out of five) are available on the sled. At the end of the round, all used Crewmen move back to «Available». The next turn order is the order in which players used their last crewmen (or passed). This is shown by the turn order markers at the top left of the board. == ACTIONS == === Draw a tile === ''Cost: 1 Crewman'' <Click on the chosen tile at the top of the board.> The player chooses either : * ONE large exploration tiles, chosen from the four available. * ONE small exploration tile, chosen from among the six available. <br/> === Refresh tiles and Draw === ''Cost: 2 Crewmen'' <Click on the "Renew deck" icon.> The player MUST: # Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve. # Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve. <br/> === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the ship or sled, then on its destination.> <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the ship or sled, then on its destination.> <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. ecefa553b528f8319a04ef171f9621b6defd20ce 838 826 2013-05-25T11:12:01Z Tirix 1962 Completed action description wikitext text/x-wiki '''''Looking for the Franklin Expedition''''' ''In 1845, Sir John Franklin led an expedition on behalf of the British Royal Navy to find and explore the last portion of the Northwest Passage. They sailed into unknown waters, and no-one ever heard from them again... Players must venture into these hazardous Arctic waters in order to discover Franklin’s fate and succeed where he failed: by finding the Northwest Passage.'' ---- In the game, prestige is awarded for exploring islands and straits, getting information from Inuits or Cairns about the Franklin Expedition, finding shipwrecks of the expedition, and for being among the first to find their way up to the Northwest Passage and back to Groenland. The player with the most Prestige points at the end of the game is the winner. In case of a tie, the first tied player to have returned to Greenland is the winner. == GAME CYCLE == The game is divided into ten rounds. At the end of each round, the solar disc moves, and part of the board above the sun freezes into ice or melts back to sea. During one round, player will take up to 7 actions, in turn. Actions can be taken either from the ship, using crewmen on the ship, or from the sled, using crewmen on the sled. At the end of the round, all used Crewmen move back to «Available». The next turn order is the order in which players used their last crewmen (or passed). This is shown by the turn order markers at the top left of the board. == ACTIONS == === Draw a tile === ''Cost: 1 Crewman'' <Click on the chosen tile at the top of the board.> <br/> === Refresh tiles and Draw === ''Cost: 2 Crewmen'' <Click on the "Renew deck" icon.> The player MUST: # Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve. # Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve. <br/> === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. e58f433c9bf6661de75716fd7b6096bdece65030 Gamehelpstoneage 0 21 827 755 2013-05-16T02:09:26Z Mexiwithacan 3157 /* Place your people on the game board */ Replaced explanation of rule changes for 2- and 3-player games with what's in the official rulebook, verbatim wikitext text/x-wiki == Goal == Get the most victory points at the end of the game. You win some points: * during the game, by acquiring buildings. * at the end of the game, according to civilization cards acquired by you. == Rules summary == Each round is divided into 3 phases, which are executed in the order described: 1. The players place their people on the game board. 2. The players use the actions of their placed people. 3. The players feed their people. ===Place your people on the game board=== Players place groups of their people in places, occupying each "ring" by one people (except for the forest place having no rings). ====Special considerations when playing with fewer than 4 people==== With '''3 or 2 players''', only 2 of the 3 places: tool maker, hut, and field may be filled in each round. The third place remains empty. Naturally, the empty place can be different in each round. With '''3 players''': on each of the places: forest, clay pit, quarry, and river only 2 players may place people in each round. With '''2 players''': on each of the places: forest, clay pit, quarry, and river only 1 player may place people in each round. All remaining rules remain unchanged. ===Use the actions of your placed people=== Each player uses all his placed people in any order, and perform the corresponding actions: * '''hunting grounds, forest, clay pit, quarry, and river''': roll 1 dice per people placed and acquire corresponding resources (1 food for each full 2 on hunting grounds, 1 wood for each full 3 on forest, 1 brick for each full 4 on clay pit, 1 stone for each full 5 on quarry, 1 gold for each full 6 on river). * '''field''': increase agriculture level. * '''tool maker''': get one tool point (new tool is added, up to 3 in total, after that these tools are upgraded). * '''hut''': get one additional people. * '''building card''': buy the building with resources, scoring some points. * '''civilization card''': buy the card with a number of resources (of any kind) depending on its position (1 to 4 resources depicted above the card). Then the immediate effect of the card is applied. ===Resources=== hunting grounds, forest, clay pit, quarry, and river: Roll 1 dice per people and take corresponding resources: * 1 food for each full 2 on hunting grounds, * 1 wood for each full 3 on forest, * 1 brick for each full 4 on clay pit, * 1 stone for each full 5 on quarry, * 1 gold for each full 6 on river. You may use tools to increase the dice result and take more resources. ===Buildings=== Pay the building cost to get the building and receive points. If the building cost is not fixed (question mark in the corner of the card), you win points for each of the resources used to acquire this building, depending on their values (3 for each wood, 4 for each brick, ...). ===Civilization card details=== Each card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card). Place the mouse cursor on each card to see details in the tooltip. Note that at the list of your acquired civilization cards you will see only the bottom half of each card, for that top half is not relevant anymore. ===Feed your people=== Each agriculture level automatically give you 1 food. You must provide 1 food per person. You may use any resource to feed your people if there is not enough food. If you don't manage (or choose not) to feed your people by means above, you lose 10 points as a penalty. ===Game end=== The game ends when: * there are no more civilization cards at the beginning of a round * one building stack is empty at the end of a round Final number of points for each player is summed out of * points earned during the game by acquiring buildings, minus food penalties, * multipliers denoted at the bottom halfs of civilization cards collected (like number of different culture cards, number of people, tool level etc). * each resource that a player has on his player board scores 1 point 892f6c221390ffc0b9cef0a00215b3530435ca93 Practical debugging 0 100 828 660 2013-05-19T19:32:34Z Een 3 /* Debugging my PHP game logic (or my view) */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> === Add traces to your code === You can use the following functions in your game to add server side logging: '''self::debug( $message )''' '''self::trace( $message )''' '''self::warn( $message )''' '''self::error( $message )''' To see the logs, you should check the "Current table error log" in the [[Studio_back-office|Studio backoffice]]. This can be useful when you need to follow the flow of your code and not just stop it to see how it goes at some point. Only the error log level will appear in production. This level should be used only for critical problems. Other levels will show only in the development environment and can be used as you see fit. == Debugging my HTML/CSS layout == Situation examples: * why my game element doesn't show up in the interface? * why my CSS property hasn't been applied to this element? * why this game element is displayed at this position? A first useful tip when an element does not show up in the interface is to give it a red background: <pre> #my_element { ... some CSS definitions ... background-color: red; } </pre> This way, you know if the element is not visible because of some of its CSS property or because of anything else. Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property. Using Chrome "Elements" tab (thre first one), you can: * See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code. * Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles. * You can even modify directly some CSS property and see if how it looks immediately on the game interface. == Debugging my Javascript game interface logic == Compare to PHP debugging, Javascript debugging can sometimes be painful. Here's are some tips to make your life easier while developing and debugging Javascript: === Do complex things on PHP side === PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first. The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property. Note: check Reversi example for this. === Add traces in your code === You can use the following: '''console.log( variable_to_inspect )''' It will give you the object structure of the variable in the Javascript console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. '''alert( variable_to_inspect )''' It will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. == Some frequent errors == === when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." === Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. === when refreshing the web page, the interface remains on "Application loading..." === In this case, you probably have a syntax error in your Javascript code, and the interface refuses to load. To find this error, check if there is an error message in the Javascript console (F12). If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition. === When I do a move, I got "Move recorded, waiting for update ..." forever === "Move recorded" means that your ajaxcall request has been sent to the server and returned normally. "Waiting for update" means that your client interface is waiting for some notifications from the server that correspond to the move we just did. If this message stays forever, it is probably that your PHP code does not send any notification when the move happens, which is abnormal. To fix this: add a notifyAllPlayers or a notifyPlayer call in your PHP code. === Some player action is triggered randomly when I click somewhere on the game area === You probably used "dojo.connect" on a null object. In this case, dojo.connect associate the event (ex: "onclick") to the whole game area. Most of the time it happens in this situation, when my_object element does not exists: <pre> dojo.connect( $("my_object"), "onclick", this, function() { ... } </pre> To determine if this is the case, place "alert( $("my_object") )" before the dojo.connect to check if the object exists or not. === Javascript does not know how to sum two numbers === Be careful when you manipulate integers returned by notifications: most of the time, Javascript considers they are Strings and not Integers. As a result: <pre> var i=1; i += notif.args.increment; // With notif.args.increment='1' alert( i ); // i=11 instead of 2 !! Javascript concatenate 2 strings ! </pre> To solve this, you should use the "toint" function: <pre> var i=1; i += toint( notif.args.increment ); // With notif.args.increment='1' alert( i ); // i=2 :) </pre> === Javascript: do not use substr with negative numbers === To get the last characters of a string, use "slice" instead of "substr" which has a bug on IE: <pre> var three_last_characters = string.substr( -3 ); // Wrong var three_last_characters = string.slice( -3 ); // Correct </pre> 750417058c1bb321927449e3554900012f94de24 829 828 2013-05-19T20:14:01Z Een 3 /* Add traces to your code */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" in the [[Studio_back-office|Studio backoffice]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> === Add traces to your code === You can use the following functions in your game to add server side logging: '''self::debug( $message );''' // debug level logging '''self::trace( $message );''' // info level logging '''self::warn( $message );''' // warning level logging '''self::error( $message );''' // error level logging To see the logs, you should check the "Current table error log" in the [[Studio_back-office|Studio backoffice]]. This can be useful when you need to follow the flow of your code and not just stop it to see how it goes at some point. Only the error log level will appear in production. This level should be used only for critical problems. Other levels will show only in the development environment and can be used as you see fit. == Debugging my HTML/CSS layout == Situation examples: * why my game element doesn't show up in the interface? * why my CSS property hasn't been applied to this element? * why this game element is displayed at this position? A first useful tip when an element does not show up in the interface is to give it a red background: <pre> #my_element { ... some CSS definitions ... background-color: red; } </pre> This way, you know if the element is not visible because of some of its CSS property or because of anything else. Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property. Using Chrome "Elements" tab (thre first one), you can: * See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code. * Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles. * You can even modify directly some CSS property and see if how it looks immediately on the game interface. == Debugging my Javascript game interface logic == Compare to PHP debugging, Javascript debugging can sometimes be painful. Here's are some tips to make your life easier while developing and debugging Javascript: === Do complex things on PHP side === PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first. The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property. Note: check Reversi example for this. === Add traces in your code === You can use the following: '''console.log( variable_to_inspect )''' It will give you the object structure of the variable in the Javascript console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. '''alert( variable_to_inspect )''' It will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. == Some frequent errors == === when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." === Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. === when refreshing the web page, the interface remains on "Application loading..." === In this case, you probably have a syntax error in your Javascript code, and the interface refuses to load. To find this error, check if there is an error message in the Javascript console (F12). If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition. === When I do a move, I got "Move recorded, waiting for update ..." forever === "Move recorded" means that your ajaxcall request has been sent to the server and returned normally. "Waiting for update" means that your client interface is waiting for some notifications from the server that correspond to the move we just did. If this message stays forever, it is probably that your PHP code does not send any notification when the move happens, which is abnormal. To fix this: add a notifyAllPlayers or a notifyPlayer call in your PHP code. === Some player action is triggered randomly when I click somewhere on the game area === You probably used "dojo.connect" on a null object. In this case, dojo.connect associate the event (ex: "onclick") to the whole game area. Most of the time it happens in this situation, when my_object element does not exists: <pre> dojo.connect( $("my_object"), "onclick", this, function() { ... } </pre> To determine if this is the case, place "alert( $("my_object") )" before the dojo.connect to check if the object exists or not. === Javascript does not know how to sum two numbers === Be careful when you manipulate integers returned by notifications: most of the time, Javascript considers they are Strings and not Integers. As a result: <pre> var i=1; i += notif.args.increment; // With notif.args.increment='1' alert( i ); // i=11 instead of 2 !! Javascript concatenate 2 strings ! </pre> To solve this, you should use the "toint" function: <pre> var i=1; i += toint( notif.args.increment ); // With notif.args.increment='1' alert( i ); // i=2 :) </pre> === Javascript: do not use substr with negative numbers === To get the last characters of a string, use "slice" instead of "substr" which has a bug on IE: <pre> var three_last_characters = string.substr( -3 ); // Wrong var three_last_characters = string.slice( -3 ); // Correct </pre> ac98a8a9b9102f90c29db809630e8f484835d624 Gamehelphearts 0 52 830 726 2013-05-20T13:03:03Z Sourisdudesert 1 wikitext text/x-wiki Hearts is a card game for 4 players, every man for himself. It uses the standard 52-card pack. '''Rank''' A (high) to 2 (low). '''Setup''' The entire deck is dealt, giving you a hand of 13 cards. After looking at your hand, choose three cards to pass to another player. The passing rotation is: (1st hand) to the player on your left, (2nd hand) to the player across the table, (3rd hand) to the player on your right, (4th hand) no passing. The rotation repeats until the game ends. '''Tricks''' After passing cards, the player holding the 2 of clubs leads the first trick. Each player must follow suit if possible. If you have no cards of the suit led, you may play a card of any suit. Exception: You may not play a heart or the Queen of Spades on the first trick, even if you have no clubs. The highest card of the suit led wins the trick. The winner of a trick starts the next trick. Hearts may not be led until a heart has been played (this is called "breaking" hearts). The Queen of Spades may be lead at any time. [NB: In traditional Hearts, playing the Queen of Spades also breaks hearts.] There is no trump suit. '''Scoring''' At the end of each hand, each heart taken by a player counts -1, and the Queen of Spades counts -13. If one player has taken all 13 hearts ''and'' the Queen of Spades (this is known as "shooting the moon", or "slam"), that player scores 0 and all other players score -26. Warning other players about an attempt to shoot the moon is team play, and a breach of Hearts etiquette. When one or more players reach zero, the game ends. The player with the highest score wins. '''Variants''' Normal game is 100 points. Quick game is 75 points. 30e89bee40751176339d12f280b2f8d9cb48a3ca Studio FAQ 0 53 831 779 2013-05-20T13:04:57Z Sourisdudesert 1 /* I added some game options / some game statistics, but they don't show? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the [http://winscp.net/ WinSCP client]. == I can't edit the files in my game directory, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == I can't access the Studio back-office, I get a 'Not authorized' error message? == You should first connect to the Studio website (with any of your <developer name><number> accounts). As the authentication is shared with the back-office, then you will be able to access it. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. Check [[Translations]] to see how to make your game translatable. == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == When you modify these 2 files, you need to deploy the update from your BGA backoffice page. == Should I use images free from copyright? == If you are developing a game in the public domain, yes (or you can make your own if you feel it's better). If you are developing a game for which we have a licence, we will usually provide art files from the publisher. c45f3903b02b0d17a05cfa31d8138ad13de036b2 Game interface stylesheet: yourgamename.css 0 96 832 683 2013-05-20T13:14:58Z Sourisdudesert 1 wikitext text/x-wiki This is the CSS stylesheet of your game User Interface. Styles defined on this file will be applied to the HTML elements you define in your HTML template (yourgame_yourgame.tpl), and to HTML elements you create dynamically with Javascript. Usually, you are using CSS to: 1°) define the overall layout of your game (ex: place the board on the top left, place player's hand beside, place the deck on the right, ...). 2°) create your CSS-sprites: All images of your games should be gathered into a small number of image files. Then, using background-image and background-position CSS properties, you create HTML blocks that can display these images correctly. Example: <pre> Example of CSS sprites (a black token and a white token, 20x20px each, embedded in the same "tokens.png" 40x20px image): .white_token { background-image: url('../../img/emptygame/tokens.png'); background-position: 0px 0px; } .black_token { background-image: url('../../img/emptygame/tokens.png'); background-position: -20px 0px; } .token { width: 20px; height: 20px; background-repeat: none; } </pre> 3°) ... anything else: It is really easy to add and remove CSS classes dynamically from your Javascript with dojo.addClass and dojo.removeClass. It is also easy to check if an element has a class (dojo.hasClass) or to get all elements with a specific class (dojo.query). This is why, very often, using CSS classes for the logic of your user interface allow you to do complex thing easily. Note: on the production platform, this file will be compressed and comments will be removed. Consequently, don't hesitate to put as many comments as necessary. Important: ALL the CSS directives for your game must be included in this CSS file. You can't create additional CSS files and import them. == Warning: using Z-index == You may use z-index CSS property in your game interface, but you should pay attention to the following: BGA dialogs are displayed with a z-index of 950. If you want to use z-index safely, you should use value '''lower than 900'''. About z-index: don't forget that if you are using a z-index, your element will be displayed above all elements that do not have a z-index. So it's no use to have big z-index values: 1 is enough most of the time :) == spectatorMode == When a spectator (= a player that is not part of the game) is viewing a game, the BGA framework add the CSS class "spectatorMode" to the wrapping HTML tag of your game. This way, if you want to apply a special style to some elements of your game for spectators, you can do this in your CSS: <pre> .spectatorMode #your_element_id { /* your special style */ } </pre> The most common usage of this is to hide some elements to spectators. For example, to hide "my hand" elements: <pre> .spectatorMode #my_hand { display: none; } </pre> 1a49ab7082c77d4a53a5d5ceb8de2e5022b7c059 Game interface logic: yourgamename.js 0 88 833 728 2013-05-20T19:18:50Z Sourisdudesert 1 /* Animations */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "AnimateProperty". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Reversi example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 8cd1006ed8d671520c0a8a0a1280dad598241c58 834 833 2013-05-20T19:23:38Z Sourisdudesert 1 /* Animations */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Reversi example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> dd34a1edd72c4ec2e3ea05e293be06a58723bd1c Main game logic: yourgamename.game.php 0 86 835 758 2013-05-21T16:24:52Z Tilalilalou 2792 /* Zombie mode */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this: <pre> $this->tie_breaker_description = self::_("Describe here your tie breaker formula"); </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaSystemVisibleException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaSystemVisibleException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. d1eb49ba1db74c83e8b9894d730fff16f76acca5 837 835 2013-05-22T09:01:51Z Sourisdudesert 1 wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your Constructor method like this: <pre> $this->tie_breaker_description = self::_("Describe here your tie breaker formula"); </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. 558ac70cea14f3ea2d2f6a5577f79daacfd7ca0e Gamehelpyatzy 0 122 840 2013-05-28T02:42:36Z Ryanmc 3227 Created page with "Be aware the rules linked from Wikipedia are NOT the rules implemented. The rules implemented vary a great deal from the real rules, and make a dive game even more luck based...." wikitext text/x-wiki Be aware the rules linked from Wikipedia are NOT the rules implemented. The rules implemented vary a great deal from the real rules, and make a dive game even more luck based. The rules for 3 of a kind, 4 of a kind, small straight, and large straight are all different. b651128ff941751e18c98776abb1b7d9f81e2da6 841 840 2013-05-28T02:44:47Z Ryanmc 3227 wikitext text/x-wiki Be aware the rules linked from Wikipedia are NOT the rules implemented. The rules implemented vary a great deal from the real rules, and make a dive game even more luck based. The rules for 3 of a kind, 4 of a kind, small straight, and large straight are all different. In this implementation 3 and 4 of a kind only counts the dice used in the pairing, not the other dice. The small straight is completely different, rather than being a 4 long straight it is explicitly a straight of 1 - 2 - 3 - 4 - 5. The large straight is only a straight of 2 - 3 - 4 - 5 - 6. This makes the odds identical for both straights, but has the large still worth more points. 5a33aea3e935344464ef886108e982d0a91b4b81 842 841 2013-05-28T02:45:38Z Ryanmc 3227 wikitext text/x-wiki Be aware the rules linked from Wikipedia are NOT the rules implemented. The rules implemented vary a great deal from the real rules, and make the game much more random and luck-based. The rules for 3 of a kind, 4 of a kind, small straight, and large straight are all different. In this implementation 3 and 4 of a kind only counts the dice used in the pairing, not the other dice. The small straight is completely different, rather than being a 4 long straight it is explicitly a straight of 1 - 2 - 3 - 4 - 5. The large straight is only a straight of 2 - 3 - 4 - 5 - 6. This makes the odds identical for both straights, but has the large still worth more points. 24726458c99dbf8c7b6939aa0d6508a2b49bc5de Gamehelpraceforthegalaxy 0 41 843 193 2013-05-28T12:28:48Z Sternenfee83 3127 wikitext text/x-wiki In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments. There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins. You may drag a resource (single-coloured small card) to a consumption power to consume it. 7adcc6f45854f68b93b0161eeb54cf8e91ce7e8d Gamehelpseasons 0 43 844 784 2013-05-28T12:34:12Z Sternenfee83 3127 wikitext text/x-wiki Season is a game of generating points (crystals) by choosing the correct combination of dice and the activation of card powers. The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be returned to the player on the starting of each cycle. Each player can choose only one die per turn. The effects are as follows: ''Star'' - increase the maximum card player can summon (max 15) ''Elements'' - Gain an energy of the element shown (water, earth, air, fire) ''Numbers'' - Gain the number of Crystals as indicated by the number ''Square card'' - Draw a card ''Dice with frames surrounding'' - Allow user to transmute energy into crystal (depend on which part of the game is at) ''Dots'' - Indicate how fast the marker progresses through the seasons cycle There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There are 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice). At the end of the game the points are calculated by adding the numbers on each played card and the crystal owned and substracting 5 points for each power card remaining in hand. The player with the most victory points wins. Note: Users need to discard energy immediately if the energy is more than the slots allocated. If a card allows you to summon another card but you have no space for this second card then it (the second card) will be discarded with no refund. == Difficulty levels: == '''Apprentice wizard level''' In order to make the game easier to learn, there are “pre-constructed” sets of nine power cards. Instead of taking step 1 of the first game phase, each player gets one of these sets. '''Magician level''' Only the power cards numbered 1 to 30 are in play. These cards have easy to grasp effects and will allow you to slowly discover the world of Seasons. '''Archmage level''' All 50 kinds of power cards are in play. The cards numbered 31 through 50 have more complex effects than the basic cards, but will allow you to extend the fun of playing by discovering new effects and combinations. 4601b4113946cbb3689946db68fb320b36bf1241 Moderationpolicy 0 123 845 2013-05-30T09:10:34Z Sourisdudesert 1 Created page with "fff" wikitext text/x-wiki fff f6949a8c7d5b90b4a698660bbfb9431503fbb995 846 845 2013-05-30T09:16:56Z Sourisdudesert 1 wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. 3ee8f8ae18afb549b01482b3d46240a70c77286b 847 846 2013-05-30T09:18:38Z Sourisdudesert 1 wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- | ! scope="col" | Titre col. A ! scope="col" | Titre col. B ! scope="col" | Titre col. C |- ! scope="row" | Titre ligne 1 | Donnée 1A | Donnée 1B | Donnée 1C |- ! scope="row" | Titre ligne 2 | Donnée 2A | Donnée 2B | Donnée 2C |- ! scope="row" | Titre ligne 3 | Donnée 3A | Donnée 3B | Donnée 3C |} 6ae857612b37650f114fa721c3a5a5abdb5018d1 848 847 2013-05-30T09:19:59Z Sourisdudesert 1 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- | ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! scope="row" | Titre ligne 1 | Donnée 1A | Donnée 1B | Donnée 1C |- ! scope="row" | Titre ligne 2 | Donnée 2A | Donnée 2B | Donnée 2C |- ! scope="row" | Titre ligne 3 | Donnée 3A | Donnée 3B | Donnée 3C |} 4991abca78b6669759c1e7fe1371aed63e559cf9 849 848 2013-05-30T09:28:47Z Sourisdudesert 1 /* General rules */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- | ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! scope="row" | Titre ligne 1 | Donnée 1A | Donnée 1B | Donnée 1C |- ! scope="row" | Titre ligne 2 | Donnée 2A | Donnée 2B | Donnée 2C |- ! scope="row" | Titre ligne 3 | Donnée 3A | Donnée 3B | Donnée 3C |} 5a0d60aab93a8b90f81fc71a8328364d7efa13fe Moderationpolicy 0 123 850 849 2013-05-30T09:29:32Z Sourisdudesert 1 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- | ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Donnée 1A | Donnée 1A | Donnée 1B | Donnée 1C |- ! Donnée 1A | Donnée 2A | Donnée 2B | Donnée 2C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |} 4d8038cf38fb161ac98f3a025e4eb5033f147b0a 851 850 2013-05-30T09:38:11Z Sourisdudesert 1 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |} 87a132a31b14d541809b5f0cd1b8aa4789750a37 852 851 2013-05-30T09:42:40Z Sourisdudesert 1 /* General rules */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games player. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |} 65b38ed4d46b022c0ccce6a65ce099891e091650 853 852 2013-05-30T09:51:19Z Sourisdudesert 1 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games player. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- |} 0ac9b3ec502c18ff1f45e58dc2c3742c587bf1ae 854 853 2013-05-30T09:59:42Z Sourisdudesert 1 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games player. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: porn, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (porn, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- |} 934bd58f5f40ff95414519ec5ada22b98e0f1d14 855 854 2013-05-30T10:05:16Z Sourisdudesert 1 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games player. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: porn, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (porn, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate. |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- |} 1b3b4318420c869b396c0be9c3512ff35afe50c9 856 855 2013-05-30T10:07:32Z Sourisdudesert 1 /* Player profile influence */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games player. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). === Incomplete reports === Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: porn, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (porn, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate. |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- |} 9043dcf975efceb574d1aa72e2526aa26923bc53 857 856 2013-05-30T10:14:21Z Sourisdudesert 1 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games player. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). === Incomplete reports === Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: porn, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (porn, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate. |- ! Table description | Inappropriate table description | If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Kingmaking | Kingmaking action during a game | The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- |} 7d97e2d01a1118a2f9a09532db522f4f273317c3 858 857 2013-05-30T10:20:40Z Sourisdudesert 1 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games player. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). === Incomplete reports === Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: porn, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (porn, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate. |- ! Table description | Inappropriate table description | If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Kingmaking | Kingmaking action during a game | The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Bug exploit | Exploit a known bug during a game | The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned. | No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset will be done. |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- |} 652fc40f9ec94d9d3fb458ab0f9ae63380d39ece 859 858 2013-05-30T10:21:14Z Sourisdudesert 1 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games player. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). === Incomplete reports === Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: porn, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (porn, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate. |- ! Table description | Inappropriate table description | If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Kingmaking | Kingmaking action during a game | The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Bug exploit | Exploit a known bug during a game | The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned. | No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done. |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- |} 1868411fd8423695a638e416421d3aa1ed75f6b7 860 859 2013-05-30T10:25:54Z Sourisdudesert 1 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games player. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). === Incomplete reports === Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: porn, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (porn, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate. |- ! Table description | Inappropriate table description | If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Kingmaking | Kingmaking action during a game | The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Bug exploit | Exploit a known bug during a game | The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned. | No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done. |- ! Private information | Some player gives some private information during the game | Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong voluntee to kill the pleasure of the game by giving some private information during the game. | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- |} 22cd9d141acbe98da1c8d1bc8baf7fc89b6f1515 861 860 2013-05-30T10:34:18Z Sourisdudesert 1 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games player. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). === Incomplete reports === Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: porn, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (porn, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate. |- ! Table description | Inappropriate table description | If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Kingmaking | Kingmaking action during a game | The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Bug exploit | Exploit a known bug during a game | The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned. | No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done. |- ! Private information | Some player gives some private information during the game | Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong voluntee to kill the pleasure of the game by giving some private information during the game. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Multiple accounts | A player is using multiple accounts (most of the time: to boost his ELO rank) | The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. This is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP adress, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way. | For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games. |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- ! Donnée 1A | Donnée 3A | Donnée 3B | Donnée 3C |- |} e68acba7624471111338d95c073aa8a7a69a368b 862 861 2013-05-30T10:39:38Z Sourisdudesert 1 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: _ the player has been reported several time for the same type of case. _ the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. _ on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games player. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). === Incomplete reports === Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: porn, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (porn, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate. |- ! Table description | Inappropriate table description | If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Kingmaking | Kingmaking action during a game | The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Bug exploit | Exploit a known bug during a game | The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned. | No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done. |- ! Private information | Some player gives some private information during the game | Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong voluntee to kill the pleasure of the game by giving some private information during the game. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Multiple accounts | A player is using multiple accounts (most of the time: to boost his ELO rank) | The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. This is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP adress, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way. | For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games. |- ! Something else | Tranlation stealing / vandalism | The player is writing inapropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership, | Immediate ban from the website (to avoid vandalism). |- ! Something else | Player is slow to play | Players have the right to think as long as they do not go over their alloted time. If the player is slow on purpose, the good answer is: thumb down. | No penalty |- ! Something else | Player quit the game before the end | In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else. | No penalty |- |} 6a2e94ac4dd960b596e6862a25383fe59427855e 863 862 2013-05-30T18:44:30Z Een 3 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: * the player has been reported several time for the same type of case. * the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. * on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games player. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). === Incomplete reports === Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: porn, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (porn, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate. |- ! Table description | Inappropriate table description | If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Kingmaking | Kingmaking action during a game | The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Bug exploit | Exploit a known bug during a game | The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned. | No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done. |- ! Private information | Some player gives some private information during the game | Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong voluntee to kill the pleasure of the game by giving some private information during the game. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Multiple accounts | A player is using multiple accounts (most of the time: to boost his ELO rank) | The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. This is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP adress, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way. | For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games. |- ! Something else | Tranlation stealing / vandalism | The player is writing inapropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership, | Immediate ban from the website (to avoid vandalism). |- ! Something else | Player is slow to play | Players have the right to think as long as they do not go over their alloted time. If the player is slow on purpose, the good answer is: thumb down. | No penalty |- ! Something else | Player quit the game before the end | In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else. | No penalty |- |} 93f81aa01f96a0d3c2096e23f0690a7d548f371b 864 863 2013-05-30T18:44:44Z Een 3 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: * the player has been reported several times for the same type of case. * the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. * on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators gives more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games player. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). === Incomplete reports === Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: porn, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (porn, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate. |- ! Table description | Inappropriate table description | If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Kingmaking | Kingmaking action during a game | The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Bug exploit | Exploit a known bug during a game | The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned. | No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done. |- ! Private information | Some player gives some private information during the game | Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong voluntee to kill the pleasure of the game by giving some private information during the game. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Multiple accounts | A player is using multiple accounts (most of the time: to boost his ELO rank) | The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. This is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP adress, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way. | For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games. |- ! Something else | Tranlation stealing / vandalism | The player is writing inapropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership, | Immediate ban from the website (to avoid vandalism). |- ! Something else | Player is slow to play | Players have the right to think as long as they do not go over their alloted time. If the player is slow on purpose, the good answer is: thumb down. | No penalty |- ! Something else | Player quit the game before the end | In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else. | No penalty |- |} 1939137892ffed5f2613689baae03d0945413f78 865 864 2013-05-30T18:52:15Z Een 3 /* Player profile influence */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: * the player has been reported several times for the same type of case. * the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. * on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators give more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games player. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). === Incomplete reports === Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: porn, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (porn, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate. |- ! Table description | Inappropriate table description | If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Kingmaking | Kingmaking action during a game | The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Bug exploit | Exploit a known bug during a game | The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned. | No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done. |- ! Private information | Some player gives some private information during the game | Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong voluntee to kill the pleasure of the game by giving some private information during the game. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Multiple accounts | A player is using multiple accounts (most of the time: to boost his ELO rank) | The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. This is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP adress, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way. | For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games. |- ! Something else | Tranlation stealing / vandalism | The player is writing inapropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership, | Immediate ban from the website (to avoid vandalism). |- ! Something else | Player is slow to play | Players have the right to think as long as they do not go over their alloted time. If the player is slow on purpose, the good answer is: thumb down. | No penalty |- ! Something else | Player quit the game before the end | In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else. | No penalty |- |} 68d4eabd3846dfb8f22862ab8bbdaba0c8329ab6 866 865 2013-05-30T18:52:46Z Een 3 /* Player profile influence */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: * the player has been reported several times for the same type of case. * the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. * on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators give more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games played. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). === Incomplete reports === Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: porn, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (porn, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one notice the username until now, it is probably not inappropriate. |- ! Table description | Inappropriate table description | If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Kingmaking | Kingmaking action during a game | The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it have to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Bug exploit | Exploit a known bug during a game | The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned. | No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done. |- ! Private information | Some player gives some private information during the game | Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong voluntee to kill the pleasure of the game by giving some private information during the game. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Multiple accounts | A player is using multiple accounts (most of the time: to boost his ELO rank) | The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. This is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP adress, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way. | For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games. |- ! Something else | Tranlation stealing / vandalism | The player is writing inapropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership, | Immediate ban from the website (to avoid vandalism). |- ! Something else | Player is slow to play | Players have the right to think as long as they do not go over their alloted time. If the player is slow on purpose, the good answer is: thumb down. | No penalty |- ! Something else | Player quit the game before the end | In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else. | No penalty |- |} 564f5ed8ba30da2f5125e2ed47d86bfa6b0d0108 867 866 2013-05-30T19:13:08Z Een 3 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: * the player has been reported several times for the same type of case. * the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. * on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators give more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games played. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). === Incomplete reports === Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: porn, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (porn, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one noticed the username until now, it is probably not inappropriate. |- ! Table description | Inappropriate table description | If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Kingmaking | Kingmaking action during a game | The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it has to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Bug exploit | Exploit a known bug during a game | The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned. | No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done. |- ! Private information | Some player gives some private information during the game | Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong intent to kill the pleasure of the game by giving some private information during the game. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Multiple accounts | A player is using multiple accounts (most of the time: to boost his ELO rank) | The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. It is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP address, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way. | For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games. |- ! Something else | Translation stealing / vandalism | The player is writing inappropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership, | Immediate ban from the website (to avoid vandalism). |- ! Something else | Player is slow to play | Players have the right to think as long as they do not go over their allotted time. If the player is slow on purpose, the good answer is: thumb down. | No penalty |- ! Something else | Player quit the game before the end | In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else. | No penalty |- |} d6bd98861dfb4fa6b1ad8b145d252c8f61df7843 Gamehelpreversi 0 124 868 2013-05-31T20:04:56Z Elisha 2997 Created page with "[English Rules: Link][http://en.wikipedia.org/wiki/Reversi]" wikitext text/x-wiki [English Rules: Link][http://en.wikipedia.org/wiki/Reversi] 245acab3bf59561ee3167722bfe3b03c5fb3d769 Gamehelpstoneage 0 21 869 827 2013-06-01T05:13:44Z Crazyamazing 3028 Minor rules clarifications wikitext text/x-wiki == Goal == Gain the most Victory Points by the end of the game. There are two ways to gain points: * Acquiring buildings during the game for either a fixed or variable amount * Acquiring Civilization cards during the game that give extra points at the end of the game == Rules summary == Each round is divided into 3 phases, which are executed in the order described: 1. The players take turns placing their people on the game board. 2. The players use the actions of their placed people all at once in turn order. 3. The players feed their people. ===Phase 1:=== ===Place People on the Board=== In turn order, one area at a time, players place one or more of their people in the different areas of the board. Each "ring" in each area of the board can only be occupied by one person. The exception to this rule is the hunting ground which can be occupied by as many people of any color every turn. ====Special Considerations When Playing With Fewer Than 4 Players==== When playing with '''2 or 3 players''': Of the non-resource areas (Tool Maker, Hut and Field) only two may be occupied per turn. The third place remains empty until the next round when With '''3 players''': Of the resource areas (Forest, Clay Pit, Quarry and River) only 2 players may place people in each round, even if there are additional spaces for additional people. With '''2 players''': Of the resource areas (Forest, Clay Pit, Quarry and River) only 1 player may place people in each round, even if there are additional spaces for additional people. All remaining rules remain unchanged when playing with fewer than 4 players. ===Phase 2:=== ===Use the Actions of Your Placed People=== In turn order each player uses all of his placed people in any order. During this phase, the following actions may be used: * '''Hunting Grounds (Food), Forest (Wood), Clay Pit (Brick), Quarry (Stone), and River (Gold)''': Roll 1 dice per person placed and acquire resources according to the number rolled (1 Food for each full 2 on Hunting Grounds, 1 Wood for each full 3 on Forest, 1 Brick for each full 4 on Clay Pit, 1 Stone for each full 5 on Quarry, 1 Gold for each full 6 on River). * '''Field''': Placing a person in the Field increases your Agriculture Level. Each turn during the Feeding Phase, your Agriculture Level is subtracted from the amount of people you have. A higher agriculture level allows you to more easily sustain your population. * '''Tool Maker''': Placing a person on the Tool Maker adds one new Tool to your player board. You only have 3 tools on your player board, and each subsequent person placed on the Tool Maker upgrades one of your tools to the next level. * '''Hut''': Place two People on the Hut to gain an extra Person to place (and feed) for the rest of the game. * '''Building Card''': Buy the building with the resources shown on the Building Card, scoring the point value shown in the top-left corner (A question mark in the top-left corner is explained below). * '''Civilization Card''': Buy the card with a number of resources (of any kind) depending on its position in the Civilization Card Track (1 to 4 resources depicted above the card). The immediate effect of the card is applied when purchase. The bottom half of Civilization Card is used for scoring at the end of the game. ===Resources=== Hunting Grounds, Forest, Clay Pit, Quarry, and River: Roll 1 dice per Person placed in that area and take the corresponding resources: * 1 Food for each full 2 on Hunting Grounds, * 1 Wood for each full 3 on Forest, * 1 Brick for each full 4 on Clay Pit, * 1 Stone for each full 5 on Quarry, * 1 Gold for each full 6 on River. You may use tools to increase the dice result and take more resources. ===Buildings=== Pay the building cost to get the Building and receive the Point Value listed in the top-left corner of the card. ''If the building cost is Not Fixed'': If there is a question mark in the corner of the card, you win points for each of the resources used to acquire this building. The values of each resource correspond to the numbers it requires when people are placed on them: * Each Wood is worth 3 Points, * Each Brick is worth 4 Points, * Each Stone is worth 5 Points, * Each Gold is worth 6 Points. ===Civilization Card Details=== Each Civilization Card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card). Place the mouse cursor on each card to see details in the tooltip. Note that at the list of your acquired civilization cards you will see only the bottom half of each card, for the top half is no longer relevant. ===Phase 3:=== ===Feed Your People=== Each Agriculture Level automatically counts as 1 Food during this phase. You must provide 1 Food per Person. In the event that you don't have enough food, you may use any resource to feed your people. If you don't manage (or choose not) to feed your people by the means above, you lose all of your food and 10 points as a penalty. ===Game End=== The game ends when either: * One Building Stack is empty at the end of a round or * There are no more Civilization Cards at the beginning of a round The final number of points for each player is decided by the conditions below: * Points earned during the game by acquiring Buildings, minus Food Penalties, * Multipliers denoted at the bottom halves of Civilization Cards collected, * Each Resource that a Player has leftover on his Player Board Scores 1 Point f71bdd22c0cc48908fc9fedbe676b0fcd488239f 870 869 2013-06-01T05:18:15Z Crazyamazing 3028 Header Editing wikitext text/x-wiki == Goal == Gain the most Victory Points by the end of the game. There are two ways to gain points: * Acquiring buildings during the game for either a fixed or variable amount * Acquiring Civilization cards during the game that give extra points at the end of the game == Rules summary == Each round is divided into 3 phases, which are executed in the order described: 1. The players take turns placing their people on the game board. 2. The players use the actions of their placed people all at once in turn order. 3. The players feed their people. == Phase 1: == ===Place People on the Board=== In turn order, one area at a time, players place one or more of their people in the different areas of the board. Each "ring" in each area of the board can only be occupied by one person. The exception to this rule is the hunting ground which can be occupied by as many people of any color every turn. ====Special Considerations When Playing With Fewer Than 4 Players==== When playing with '''2 or 3 players''': Of the non-resource areas (Tool Maker, Hut and Field) only two may be occupied per turn. The third place remains empty until the next round when With '''3 players''': Of the resource areas (Forest, Clay Pit, Quarry and River) only 2 players may place people in each round, even if there are additional spaces for additional people. With '''2 players''': Of the resource areas (Forest, Clay Pit, Quarry and River) only 1 player may place people in each round, even if there are additional spaces for additional people. All remaining rules remain unchanged when playing with fewer than 4 players. == Phase 2: == ===Use the Actions of Your Placed People=== In turn order each player uses all of his placed people in any order. During this phase, the following actions may be used: * '''Hunting Grounds (Food), Forest (Wood), Clay Pit (Brick), Quarry (Stone), and River (Gold)''': Roll 1 dice per person placed and acquire resources according to the number rolled (1 Food for each full 2 on Hunting Grounds, 1 Wood for each full 3 on Forest, 1 Brick for each full 4 on Clay Pit, 1 Stone for each full 5 on Quarry, 1 Gold for each full 6 on River). * '''Field''': Placing a person in the Field increases your Agriculture Level. Each turn during the Feeding Phase, your Agriculture Level is subtracted from the amount of people you have. A higher agriculture level allows you to more easily sustain your population. * '''Tool Maker''': Placing a person on the Tool Maker adds one new Tool to your player board. You only have 3 tools on your player board, and each subsequent person placed on the Tool Maker upgrades one of your tools to the next level. * '''Hut''': Place two People on the Hut to gain an extra Person to place (and feed) for the rest of the game. * '''Building Card''': Buy the building with the resources shown on the Building Card, scoring the point value shown in the top-left corner (A question mark in the top-left corner is explained below). * '''Civilization Card''': Buy the card with a number of resources (of any kind) depending on its position in the Civilization Card Track (1 to 4 resources depicted above the card). The immediate effect of the card is applied when purchase. The bottom half of Civilization Card is used for scoring at the end of the game. ===Resources=== Hunting Grounds, Forest, Clay Pit, Quarry, and River: Roll 1 dice per Person placed in that area and take the corresponding resources: * 1 Food for each full 2 on Hunting Grounds, * 1 Wood for each full 3 on Forest, * 1 Brick for each full 4 on Clay Pit, * 1 Stone for each full 5 on Quarry, * 1 Gold for each full 6 on River. You may use tools to increase the dice result and take more resources. ===Buildings=== Pay the building cost to get the Building and receive the Point Value listed in the top-left corner of the card. ''If the building cost is Not Fixed'': If there is a question mark in the corner of the card, you win points for each of the resources used to acquire this building. The values of each resource correspond to the numbers it requires when people are placed on them: * Each Wood is worth 3 Points, * Each Brick is worth 4 Points, * Each Stone is worth 5 Points, * Each Gold is worth 6 Points. ===Civilization Card Details=== Each Civilization Card acquired brings an immediate advantage (depicted on the top half of the card) and some multiplier for final scoring (depicted on the bottom half of the card). Place the mouse cursor on each card to see details in the tooltip. Note that at the list of your acquired civilization cards you will see only the bottom half of each card, for the top half is no longer relevant. == Phase 3: == ===Feed Your People=== Each Agriculture Level automatically counts as 1 Food during this phase. You must provide 1 Food per Person. In the event that you don't have enough food, you may use any resource to feed your people. If you don't manage (or choose not) to feed your people by the means above, you lose all of your food and 10 points as a penalty. ===Game End=== The game ends when either: * One Building Stack is empty at the end of a round or * There are no more Civilization Cards at the beginning of a round The final number of points for each player is decided by the conditions below: * Points earned during the game by acquiring Buildings, minus Food Penalties, * Multipliers denoted at the bottom halves of Civilization Cards collected, * Each Resource that a Player has leftover on his Player Board Scores 1 Point bf846958420a3a6029ddf8def947fe382ed09d03 Gamehelpniagara 0 119 871 839 2013-06-01T16:45:56Z Pejsek2 3255 better-looking gem table wikitext text/x-wiki Players paddle canoes along the Niagara river to collect gems of five different colors and bring them safely back to shore without being swept over the waterfall. To win, a player must return either: * five different colored gems * four gems of the same color * seven gems of any color The tie break is the value of the gems - the gems closer to the waterfall have a higher value. In order the gems are: {| class="wikitable" ! align="left"| Gem ! Color ! Value |- |Amethyst |Violet |1 |- |Diamond |Clear |2 |- |Amber |Yellow |3 |- |- |Sapphire |Blue |4 |- |- |Ruby |Pink |5 |} Players have a set of 7 paddle cards which they play to determine the speed of their canoes and the speed of the river. All players must select the card they will play before the players then move their canoes in turn order. Once a card has been played it is not available to play again until all 7 cards have been played. After all the players have moved their canoes the river moves causing all the canoes on the river to be swept downstream. The river moves the same number of places as the lowest value paddle card played plus or minus a modifier depending on the weather. At the beginning of the game the weather is set to 0 so there is no modification but each player also has a cloud card as part of their set of paddle cards that allows them to adjust the weather and hence make the river speed up or slow down. The number on the paddle card determines the number of spaces that the canoe moves - it costs 2 paddle points to pick up (or offload) a gem. Thus if a player chose their 5 card they could move their canoe 5 spaces *or* they could move their canoe 3 spaces and pick up a gem (or they could offload a gem and move their canoe 3 spaces). Both canoes may be moved with the same paddle card - both canoes are moved the same amount, the paddles points are not split between the canoes. When both canoes are out of the water only one can be launched in that turn. If both canoes are in the water they must both be moved using the full value of the paddle points - a player cannot chose not to move one canoe and must always use the full value of the paddle points. However if one of the canoes is out of the water a player may choose not to launch it. Canoes may only move upstream or downstream in a single turn - it is not permitted to change direction in the middle of the turn. However one canoe could move upstream and the second one downstream. Players may steal gems from other canoes, but only after moving upstream and only if they finish on the same space as the other player (and only if they have an empty canoes and hence space to load the gem). Turn order is therefore crucial for stealing. 12cc267ba3dbd74e0d23e887ffa80fc1d0f05f81 Gamehelpnorthwestpassage 0 121 872 838 2013-06-02T04:00:04Z Tirix 1962 Mentioned additional crewman cost for addititional actions wikitext text/x-wiki '''''Looking for the Franklin Expedition''''' ''In 1845, Sir John Franklin led an expedition on behalf of the British Royal Navy to find and explore the last portion of the Northwest Passage. They sailed into unknown waters, and no-one ever heard from them again... Players must venture into these hazardous Arctic waters in order to discover Franklin’s fate and succeed where he failed: by finding the Northwest Passage.'' ---- In the game, prestige is awarded for exploring islands and straits, getting information from Inuits or Cairns about the Franklin Expedition, finding shipwrecks of the expedition, and for being among the first to find their way up to the Northwest Passage and back to Groenland. The player with the most Prestige points at the end of the game is the winner. In case of a tie, the first tied player to have returned to Greenland is the winner. == GAME CYCLE == The game is divided into ten rounds. At the end of each round, the solar disc moves, and part of the board above the sun freezes into ice or melts back to sea. During one round, player will take up to 7 actions, in turn. Actions can be taken either from the ship, using crewmen on the ship, or from the sled, using crewmen on the sled. During one turn, one player can play one or more actions. However, '''all additional actions (beyond the first one) will cost one more crewman than normal'''. In order to stop playing more actions during one turn, click the blincking [End Turn] at the top of the screen. At the end of the round, all used Crewmen move back to «Available». The next turn order is the order in which players used their last crewmen (or passed). This is shown by the turn order markers at the top left of the board. == ACTIONS == === Draw a tile === ''Cost: 1 Crewman'' <Click on the chosen tile at the top of the board.> <br/> === Refresh tiles and Draw === ''Cost: 2 Crewmen'' <Click on the "Renew deck" icon.> The player MUST: # Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve. # Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve. <br/> === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. 52900610215c1c81ffdb67435634a2f1d3cc2098 873 872 2013-06-02T10:38:27Z Tirix 1962 wikitext text/x-wiki '''''Looking for the Franklin Expedition''''' ''In 1845, Sir John Franklin led an expedition on behalf of the British Royal Navy to find and explore the last portion of the Northwest Passage. They sailed into unknown waters, and no-one ever heard from them again... Players must venture into these hazardous Arctic waters in order to discover Franklin’s fate and succeed where he failed: by finding the Northwest Passage.'' ---- In the game, prestige is awarded for exploring islands and straits, getting information from Inuits or Cairns about the Franklin Expedition, finding shipwrecks of the expedition, and for being among the first to find their way up to the Northwest Passage and back to Groenland. The player with the most Prestige points at the end of the game is the winner. In case of a tie, the first tied player to have returned to Greenland is the winner. == GAME CYCLE == The game is divided into ten rounds. At the end of each round, the solar disc moves, and part of the board above the sun freezes into ice or melts back to sea. During one round, player will take up to 7 actions, in turn. Actions can be taken either from the ship, using crewmen on the ship, or from the sled, using crewmen on the sled. During one turn, one player can play one or more actions. However, '''all additional actions (beyond the first one) will cost one more crewman than normal'''. In order to stop playing more actions during one turn, click the blinking [End Turn] at the top of the screen. At the end of the round, all used Crewmen move back to «Available». The next turn order is the order in which players used their last crewmen (or passed). This is shown by the turn order markers at the top left of the board. == ACTIONS == === Draw a tile === ''Cost: 1 Crewman'' <Click on the chosen tile at the top of the board.> <br/> === Refresh tiles and Draw === ''Cost: 2 Crewmen'' <Click on the "Renew deck" icon.> The player MUST: # Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve. # Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve. <br/> === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. b1ae8800a8556d2ec55b52cf4109d6778adb2b76 Gamehelpquoridor 0 102 874 695 2013-06-02T21:22:24Z Januszk0 3262 wikitext text/x-wiki W grze może brać udział dwóch lub czterech graczy. Plansza złożona jest z 81 kwadratów, po których poruszają się pionki reprezentujące graczy. Na początku rozgrywki pionki należy ustawić po środku przeciwległych krawędzi planszy. Celem gry jest zostaniem pierwszym graczem, który dotrze do startowego rzędu przeciwnika. Można to uczynić poruszając się o jedno pole w 4 kierunkach lub stawiając ogrodzenia uniemożliwiające przejście. W rozgrywce dwuosobowej każdy posiada 10 drewnianych płytek, a w rozgrywce czteroosobowej po 5. Gracze wykonują ruch jeden po drugim w kolejności według ruchów zegara (pierwszy gracz jest losowany). Nie wolno całkowicie zablokować przeciwnika - zawsze musi istnieć przynajmniej jedno przejście. Istnieje także zasada mówiąca o możliwości przeskoczenia pionka przeciwnika w sytuacji, gdy stoją na przeciwko siebie w sąsiadujących polach. b2d49d0979a63aeb3a50507fff8df67ace68c411 889 874 2013-06-16T13:41:18Z Issity 2112 Undo revision 874 by [[Special:Contributions/Januszk0|Januszk0]] ([[User talk:Januszk0|talk]]) - Polish text was placed on English page wikitext text/x-wiki [http://heyjude0929.pixnet.net/blog/post/26923277-%5B%E9%81%8A%E6%88%B2%E4%BB%8B%E7%B4%B9%5D%E6%AD%A5%E6%AD%A5%E7%82%BA%E7%87%9Fquoridor]步步為營(zh) Corridor is a 2-player game, the object of which is to move your pawn to the other side of a 9x9 board before your opponent. You can either move your man up,down or sideways or put a fence down. Players can jump over an opponent that he is next to or jump diagonally if he is next to a fence. Players cannot jump over fences. Players can put a fence down to block an opponent, but must allow at least one path to get to his winning side. You have only 10 fences. There is a fence counter by your name. Set traps to delay the opponent and create corridors to a winning path. You can concede the game by clicking on the square by your name and clicking "Concede...". You must have completed 50% or more of your game. There is an optional starting "Off the Center Aisle" Variation. Players agree to play this variation. The first player moves sideways and the second player move sideways in the opposite direction. The players keep on moving sideways until they agree to stop. 81f6185c44e295d3d224159201b0b4d3a368fc64 Gamehelpdragonheart 0 31 875 811 2013-06-07T07:45:17Z Guszty 3271 wikitext text/x-wiki ==Summary== Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down. ==Goal== To have the most points by the end of the game. ==Game Start== At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board. ==End== The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 3 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game. In case of a tie, the player with the Great Dragon wins. ==Turns== Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship. ==Cards== There are nine types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it is. Arrows on the board indicate what cards can take what. * ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf. * ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board. * ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards. * ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress. * ''Troll'': Placing this card allows the player to take the sorceress pile. * ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board. * ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent. * ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon. * ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the table. The ship cards are then discarded. The third time that three ship cards are played ends the game and the opponent takes one final turn. * ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand. e483577692cda37d861be7c5ae5fb36d9746d21a Club Board Game Arena 0 8 876 20 2013-06-10T20:09:36Z Sourisdudesert 1 wikitext text/x-wiki ==Why can't you just have a standard donation system where I can choose any money amount ?== With this "club" system, we try to highlight players who supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time. Many websites are using a more classical approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena chooses to set 3 fixed amounts for donations in order to rely on a bigger number of small donors. ==Is it mandatory to join the club ?== Of course not. You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra : you don't need statistics to play and have fun, don't you ? As a matter of fact, most players are not club members. ==What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif == When you join Board Game Arena, your get a "beginner account" (http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif) for 30 days. This beginner account allow you to view your own ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) for each game. After 30 days, your account becomes a standard '''non member''' account (http://en.boardgamearena.com/theme/img/accounttypes/free.gif). ==What becomes of the money ?== Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost). Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)... A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone ! ff7997026610fbb6d05400848cd31c5206035eea Gamehelppylos 0 125 877 2013-06-11T07:00:32Z Stst 2180 Created page with "'''PLAYING A GAME''' Start of the game Each player alternately, puts a ball from his reserve into any hollow which he has chosen. '''Stacking on a square''' When one or more ..." wikitext text/x-wiki '''PLAYING A GAME''' Start of the game Each player alternately, puts a ball from his reserve into any hollow which he has chosen. '''Stacking on a square''' When one or more squares of balls are formed on the board or at higher levels, a player can choose to stack one of his balls on it; when it is his turn to play, he then has a choice between: - taking a ball from his reserve and placing it on the board, - placing a ball from his reserve on one of the squares of balls, - moving one of his balls already on the board and putting it on a square of balls, but only if this move raises his ball by one or more levels. This move enables him to save a ball in his reserve. A ball on the board cannot be moved if it is already supporting another balls. '''Square in the player's own color''' A player who makes a square of balls in his own color immediately takes back either one or two of his balls from the board and puts them back in his reserve; He may recover any ball belonging to him by picking them up from any level of the pyramid - including the one which he has just placed - except for those balls that support other balls. (Making several squares of balls in his own color by putting on one ball only allows the player to withdraw one or two of his balls). '''END OF THE GAME''' The winner is the one who places his last ball at the top of the pyramid '''CHILDREN’S VERSION''' To start gradually, it is possible to play without using the rules for the "square in the player's own color " - only the rules for stacking allow the player to save balls. '''VERSION FOR MATURE PLAYERS: EXTENDED''' A player takes back one or two of his balls which are on the board when he makes a square or a line in his color: To be valid, alignments must be on either the first or the second level. An alignment consists of: - 4 balls of the same color in line on the first level, - 3 balls of the same color in line on the second level. A diagonal line is not an alignment. No more than two spheres can be taken back per shot. ee24a02786352eff33532674147b377d20f947bd 878 877 2013-06-11T07:06:04Z Stst 2180 wikitext text/x-wiki '''PLAYING A GAME''' Start of the game Each player alternately, puts a ball from his reserve into any hollow which he has chosen. '''Stacking on a square''' When one or more squares of balls are formed on the board or at higher levels, a player can choose to stack one of his balls on it; when it is his turn to play, he then has a choice between: *taking a ball from his reserve and placing it on the board, *placing a ball from his reserve on one of the squares of balls, *moving one of his balls already on the board and putting it on a square of balls, but only if this move raises his ball by one or more levels. This move enables him to save a ball in his reserve. A ball on the board cannot be moved if it is already supporting another balls. '''Square in the player's own color''' A player who makes a square of balls in his own color immediately takes back either one or two of his balls from the board and puts them back in his reserve; He may recover any ball belonging to him by picking them up from any level of the pyramid - including the one which he has just placed - except for those balls that support other balls. (Making several squares of balls in his own color by putting on one ball only allows the player to withdraw one or two of his balls). '''END OF THE GAME''' The winner is the one who places his last ball at the top of the pyramid '''CHILDREN’S VERSION''' To start gradually, it is possible to play without using the rules for the "square in the player's own color " - only the rules for stacking allow the player to save balls. '''VERSION FOR MATURE PLAYERS: EXTENDED''' A player takes back one or two of his balls which are on the board when he makes a square or a line in his color: To be valid, alignments must be on either the first or the second level. An alignment consists of: *4 balls of the same color in line on the first level, *3 balls of the same color in line on the second level. A diagonal line is not an alignment. No more than two spheres can be taken back per shot. 299c9719ba294c06ae48d56d5b896b41cd64edee 879 878 2013-06-11T07:07:35Z Stst 2180 wikitext text/x-wiki ===PLAYING A GAME=== Start of the game Each player alternately, puts a ball from his reserve into any hollow which he has chosen. ===Stacking on a square=== When one or more squares of balls are formed on the board or at higher levels, a player can choose to stack one of his balls on it; when it is his turn to play, he then has a choice between: *taking a ball from his reserve and placing it on the board, *placing a ball from his reserve on one of the squares of balls, *moving one of his balls already on the board and putting it on a square of balls, but only if this move raises his ball by one or more levels. This move enables him to save a ball in his reserve. A ball on the board cannot be moved if it is already supporting another balls. ===Square in the player's own color=== A player who makes a square of balls in his own color immediately takes back either one or two of his balls from the board and puts them back in his reserve; He may recover any ball belonging to him by picking them up from any level of the pyramid - including the one which he has just placed - except for those balls that support other balls. (Making several squares of balls in his own color by putting on one ball only allows the player to withdraw one or two of his balls). ===END OF THE GAME=== The winner is the one who places his last ball at the top of the pyramid ===CHILDREN’S VERSION=== To start gradually, it is possible to play without using the rules for the "square in the player's own color " - only the rules for stacking allow the player to save balls. ===VERSION FOR MATURE PLAYERS: EXTENDED=== A player takes back one or two of his balls which are on the board when he makes a square or a line in his color: To be valid, alignments must be on either the first or the second level. An alignment consists of: *4 balls of the same color in line on the first level, *3 balls of the same color in line on the second level. A diagonal line is not an alignment. No more than two spheres can be taken back per shot. d0e1ce0f661f3b20511133289fa4c7a15d576504 880 879 2013-06-11T07:08:18Z Stst 2180 /* PLAYING A GAME */ wikitext text/x-wiki ===PLAYING A GAME=== Start of the game. Each player alternately, puts a ball from his reserve into any hollow which he has chosen. ===Stacking on a square=== When one or more squares of balls are formed on the board or at higher levels, a player can choose to stack one of his balls on it; when it is his turn to play, he then has a choice between: *taking a ball from his reserve and placing it on the board, *placing a ball from his reserve on one of the squares of balls, *moving one of his balls already on the board and putting it on a square of balls, but only if this move raises his ball by one or more levels. This move enables him to save a ball in his reserve. A ball on the board cannot be moved if it is already supporting another balls. ===Square in the player's own color=== A player who makes a square of balls in his own color immediately takes back either one or two of his balls from the board and puts them back in his reserve; He may recover any ball belonging to him by picking them up from any level of the pyramid - including the one which he has just placed - except for those balls that support other balls. (Making several squares of balls in his own color by putting on one ball only allows the player to withdraw one or two of his balls). ===END OF THE GAME=== The winner is the one who places his last ball at the top of the pyramid ===CHILDREN’S VERSION=== To start gradually, it is possible to play without using the rules for the "square in the player's own color " - only the rules for stacking allow the player to save balls. ===VERSION FOR MATURE PLAYERS: EXTENDED=== A player takes back one or two of his balls which are on the board when he makes a square or a line in his color: To be valid, alignments must be on either the first or the second level. An alignment consists of: *4 balls of the same color in line on the first level, *3 balls of the same color in line on the second level. A diagonal line is not an alignment. No more than two spheres can be taken back per shot. b47a23568de7da199140660a582cabae45f7c3b2 881 880 2013-06-11T07:09:18Z Stst 2180 /* END OF THE GAME */ wikitext text/x-wiki ===PLAYING A GAME=== Start of the game. Each player alternately, puts a ball from his reserve into any hollow which he has chosen. ===Stacking on a square=== When one or more squares of balls are formed on the board or at higher levels, a player can choose to stack one of his balls on it; when it is his turn to play, he then has a choice between: *taking a ball from his reserve and placing it on the board, *placing a ball from his reserve on one of the squares of balls, *moving one of his balls already on the board and putting it on a square of balls, but only if this move raises his ball by one or more levels. This move enables him to save a ball in his reserve. A ball on the board cannot be moved if it is already supporting another balls. ===Square in the player's own color=== A player who makes a square of balls in his own color immediately takes back either one or two of his balls from the board and puts them back in his reserve; He may recover any ball belonging to him by picking them up from any level of the pyramid - including the one which he has just placed - except for those balls that support other balls. (Making several squares of balls in his own color by putting on one ball only allows the player to withdraw one or two of his balls). ===END OF THE GAME=== The winner is the one who places his last ball at the top of the pyramid. ===CHILDREN’S VERSION=== To start gradually, it is possible to play without using the rules for the "square in the player's own color " - only the rules for stacking allow the player to save balls. ===VERSION FOR MATURE PLAYERS: EXTENDED=== A player takes back one or two of his balls which are on the board when he makes a square or a line in his color: To be valid, alignments must be on either the first or the second level. An alignment consists of: *4 balls of the same color in line on the first level, *3 balls of the same color in line on the second level. A diagonal line is not an alignment. No more than two spheres can be taken back per shot. 0873de88f4bad1c0ad90275ddb11bb3c4fc3bf33 882 881 2013-06-11T11:31:49Z Stst 2180 /* VERSION FOR MATURE PLAYERS: EXTENDED */ wikitext text/x-wiki ===PLAYING A GAME=== Start of the game. Each player alternately, puts a ball from his reserve into any hollow which he has chosen. ===Stacking on a square=== When one or more squares of balls are formed on the board or at higher levels, a player can choose to stack one of his balls on it; when it is his turn to play, he then has a choice between: *taking a ball from his reserve and placing it on the board, *placing a ball from his reserve on one of the squares of balls, *moving one of his balls already on the board and putting it on a square of balls, but only if this move raises his ball by one or more levels. This move enables him to save a ball in his reserve. A ball on the board cannot be moved if it is already supporting another balls. ===Square in the player's own color=== A player who makes a square of balls in his own color immediately takes back either one or two of his balls from the board and puts them back in his reserve; He may recover any ball belonging to him by picking them up from any level of the pyramid - including the one which he has just placed - except for those balls that support other balls. (Making several squares of balls in his own color by putting on one ball only allows the player to withdraw one or two of his balls). ===END OF THE GAME=== The winner is the one who places his last ball at the top of the pyramid. ===CHILDREN’S VERSION=== To start gradually, it is possible to play without using the rules for the "square in the player's own color " - only the rules for stacking allow the player to save balls. ===VERSION FOR MATURE PLAYERS: EXTENDED=== A player takes back one or two of his balls which are on the board when he makes a square or a line in his color: To be valid, alignments must be on either the first or the second level. An alignment consists of: *4 balls of the same color in line on the first level, *3 balls of the same color in line on the second level. A diagonal line is not an alignment. No more than two balls can be taken back per shot. cb99b4160b207e2265cc6194e3dd4073a76c87f3 883 882 2013-06-11T20:44:47Z Stst 2180 /* VERSION FOR MATURE PLAYERS: EXTENDED */ wikitext text/x-wiki ===PLAYING A GAME=== Start of the game. Each player alternately, puts a ball from his reserve into any hollow which he has chosen. ===Stacking on a square=== When one or more squares of balls are formed on the board or at higher levels, a player can choose to stack one of his balls on it; when it is his turn to play, he then has a choice between: *taking a ball from his reserve and placing it on the board, *placing a ball from his reserve on one of the squares of balls, *moving one of his balls already on the board and putting it on a square of balls, but only if this move raises his ball by one or more levels. This move enables him to save a ball in his reserve. A ball on the board cannot be moved if it is already supporting another balls. ===Square in the player's own color=== A player who makes a square of balls in his own color immediately takes back either one or two of his balls from the board and puts them back in his reserve; He may recover any ball belonging to him by picking them up from any level of the pyramid - including the one which he has just placed - except for those balls that support other balls. (Making several squares of balls in his own color by putting on one ball only allows the player to withdraw one or two of his balls). ===END OF THE GAME=== The winner is the one who places his last ball at the top of the pyramid. ===CHILDREN’S VERSION=== To start gradually, it is possible to play without using the rules for the "square in the player's own color " - only the rules for stacking allow the player to save balls. ===VERSION FOR MATURE PLAYERS: ADVANCED=== A player takes back one or two of his balls which are on the board when he makes a square or a line in his color: To be valid, alignments must be on either the first or the second level. An alignment consists of: *4 balls of the same color in line on the first level, *3 balls of the same color in line on the second level. A diagonal line is not an alignment. No more than two balls can be taken back per shot. e726a8d5e6806f118954889b3f41813310ed8709 Gamehelpunitedsquare 0 42 884 707 2013-06-12T05:36:09Z Chaotic iak 3338 wikitext text/x-wiki ==Goal== The goal is to be the player who has the most squares of his color. ==Rules== The game uses pieces of six types, where each piece is in shape of a square. The sides of each piece are colored with one of red, yellow, green, blue, so that a piece has one side for each color. Each "side" appears as a triangle. Each player on his turn puts a square next to a square already on the board. The piece may be rotated, but not reflected. The sides coinciding with previous pieces on the board must match in color. It's possible for a blank square to be adjacent to two sides of the same color, blocking said square from being occupied (because there is no piece that has two sides of the same color). When a player cannot put any piece, the turn is passed. In all other cases, the player must put some piece. Due to the appearance of a side as a triangle, matched sides form a tilted square. Each of these squares scores a point for the person holding this color. ==Ending the game== When no more piece can be put by any player, the player with the most squares of his color wins. == Game preferences == The '''colorblind''' option available for this game enables an alternative setup displaying symbols on the tokens using the great color code designed by Miguel Neiva: [http://www.coloradd.net/code.asp ColorADD]. Learning the code is easy, just take a look at the following synthesis panel: [[File:ColorADD.jpg]] '''HAVE A GOOD GAME!''' 941de17dad67e96ffda31089a82f4ccbdcdacc23 Gamehelpelfenland 0 126 885 2013-06-16T12:50:55Z Een 3 Created page with "== Goal of the game == Visiting as many cities as possible in Elfenland over 4 rounds. At the end of the 4th round, the player who collected the most Town Pieces wins. == R..." wikitext text/x-wiki == Goal of the game == Visiting as many cities as possible in Elfenland over 4 rounds. At the end of the 4th round, the player who collected the most Town Pieces wins. == Round overview == A round is split into phases: # Each player fills his hand up to 8 cards and gets a secret Transportation Counter. # One after another, each player chooses a Transportation Counter from the 5 visible or drawn from the facedown stack, until each player took 3. # One after another, each player chooses must plan a travel road by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to up the cost of traveling on this road from 1 card. # One after another, each player is going to travel from town to town. The current position of a player is shown by the Elf Boot of his color, initially set on the biggest town, Elvenhold. == Travel rules == Players can travel : * on the roads on which a Transportation Counter has been set * on the rivers * on the lakes. To travel on a road, a river or a lake, the player needs to pay with the cards in hands the cost matching the terrain of the road and the means of transport used. For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (NB: the 'Magic Cloud' Transportation Counter cannot be used to travel in the desert, as it's too hot for a Cloud over there). Also : * To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows). * To cross a lake, you need to pay two 'Raft' cards. * If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type. * If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road). == Variant == In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round. If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there. This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game. '''Have a good game!''' 368bc2b9b805fc1e45ba2d5b8717bf20d08e1285 886 885 2013-06-16T12:52:46Z Een 3 /* Round overview */ wikitext text/x-wiki == Goal of the game == Visiting as many cities as possible in Elfenland over 4 rounds. At the end of the 4th round, the player who collected the most Town Pieces wins. == Round overview == A round is split into phases: # Each player fills his hand up to 8 cards and gets a secret Transportation Counter. # One after another, each player chooses a Transportation Counter from the 5 visible or drawn from the facedown stack, until each player took 3. # One after another, each player chooses must plan a travel road by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to up the cost of traveling on this road from 1 card. # One after another, each player is going to travel from town to town. The current position of a player is shown by the Elf Boot of his color, initially set on the biggest town, Elvenhold. At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter. == Travel rules == Players can travel : * on the roads on which a Transportation Counter has been set * on the rivers * on the lakes. To travel on a road, a river or a lake, the player needs to pay with the cards in hands the cost matching the terrain of the road and the means of transport used. For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (NB: the 'Magic Cloud' Transportation Counter cannot be used to travel in the desert, as it's too hot for a Cloud over there). Also : * To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows). * To cross a lake, you need to pay two 'Raft' cards. * If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type. * If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road). == Variant == In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round. If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there. This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game. '''Have a good game!''' 5e2dabcee0f80719357b72ee48d9f8c5067a45fb 887 886 2013-06-16T12:57:28Z Een 3 /* Goal of the game */ wikitext text/x-wiki == Goal of the game == Visiting as many cities as possible in Elfenland over 4 rounds. At the end of the 4th round, the player who collected the most Town Pieces wins. We advise you to play with at least 3 players to best enjoy the game (4 or 5 is even better). A lot of the fun comes from using the counters from other players to optimise one's travels, so the more the merrier! == Round overview == A round is split into phases: # Each player fills his hand up to 8 cards and gets a secret Transportation Counter. # One after another, each player chooses a Transportation Counter from the 5 visible or drawn from the facedown stack, until each player took 3. # One after another, each player chooses must plan a travel road by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to up the cost of traveling on this road from 1 card. # One after another, each player is going to travel from town to town. The current position of a player is shown by the Elf Boot of his color, initially set on the biggest town, Elvenhold. At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter. == Travel rules == Players can travel : * on the roads on which a Transportation Counter has been set * on the rivers * on the lakes. To travel on a road, a river or a lake, the player needs to pay with the cards in hands the cost matching the terrain of the road and the means of transport used. For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (NB: the 'Magic Cloud' Transportation Counter cannot be used to travel in the desert, as it's too hot for a Cloud over there). Also : * To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows). * To cross a lake, you need to pay two 'Raft' cards. * If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type. * If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road). == Variant == In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round. If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there. This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game. '''Have a good game!''' 3c9887d2684d2aa2d6260a89e25c0ee3d74738fd 888 887 2013-06-16T13:00:56Z Een 3 /* Goal of the game */ wikitext text/x-wiki == Goal of the game == Visiting as many cities as possible in Elfenland over 4 rounds. At the end of the 4th round, the player who collected the most Town Pieces wins. We advise you to play with at least 3 players to best enjoy the game (4 or 5 is even better). A lot of the fun comes from using the Transportation Counters set by other players to optimise one's travels, so the more the merrier! == Round overview == A round is split into phases: # Each player fills his hand up to 8 cards and gets a secret Transportation Counter. # One after another, each player chooses a Transportation Counter from the 5 visible or drawn from the facedown stack, until each player took 3. # One after another, each player chooses must plan a travel road by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to up the cost of traveling on this road from 1 card. # One after another, each player is going to travel from town to town. The current position of a player is shown by the Elf Boot of his color, initially set on the biggest town, Elvenhold. At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter. == Travel rules == Players can travel : * on the roads on which a Transportation Counter has been set * on the rivers * on the lakes. To travel on a road, a river or a lake, the player needs to pay with the cards in hands the cost matching the terrain of the road and the means of transport used. For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (NB: the 'Magic Cloud' Transportation Counter cannot be used to travel in the desert, as it's too hot for a Cloud over there). Also : * To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows). * To cross a lake, you need to pay two 'Raft' cards. * If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type. * If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road). == Variant == In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round. If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there. This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game. '''Have a good game!''' 5109a7a3a58a66f70c401dfa41eab700fceabcdf Gamehelpyatzy 0 122 890 842 2013-06-19T05:07:45Z Wonderer 3397 wikitext text/x-wiki Be aware the rules linked from Wikipedia are NOT the rules implemented. The rules implemented vary a great deal from the real rules, and make the game much more random and luck-based. The rules for 3 of a kind, 4 of a kind, small straight, and large straight are all different. In this implementation 3 and 4 of a kind only counts the dice used in the pairing, not the other dice. This makes the odds identical for both straights, but has the large still worth more points. 08961c163bea1dc1e7722529d8499e07e5d63525 891 890 2013-06-19T05:11:03Z Wonderer 3397 Blanked the page wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Studio 0 49 892 793 2013-06-20T19:19:17Z Sourisdudesert 1 /* BGA Studio user guide */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the latest information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) See announcement here: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973 == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum''']. == BGA Studio documentation == === BGA Studio Framework reference === This part of the documentation focuses on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a &lt;div&gt; element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. * [[Tools and tips of BGA Studio]] * [[Practical debugging]] * [[Studio logs]] * [[Studio back-office]] * [[Studio FAQ]] == BGA Developer team organization == * [[Steps to create a BGA game]] * [[Post-release phase]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] b5935f96db32b7aa0f0a029e5a5011b29c677061 Studio logs 0 127 893 2013-06-20T19:19:29Z Sourisdudesert 1 Created page with "(to be written)" wikitext text/x-wiki (to be written) a5a10fffe3d6647651bdea1a52be1345e04bd462 894 893 2013-06-20T19:58:36Z Sourisdudesert 1 wikitext text/x-wiki BGA Studio logs are available directly from your game development interface. Logs allows you to check out what happened recently on server and to debug your game. == BGA request&SQL logs == On this log, you can see: === Your requests === Example: 20/06 21:50:56 [info] [T403] [4/mytest0] /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 Note that the best way to check your Ajax request is to read the [[http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#Input.2FOutput_debugging_section Input/Output section]]. === Request responses === Example: 20/06 21:50:56 [notice] [T403] [4/mytest0] OK-0 169 d141 c8 e0 I9 A158 V0 T0 /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 You can recognize a response because it contains [notice]. Usually, there is one response for each request. Let's details the beginning of the log: * 20/06 21:50:56: the date * [notice] * [T403]: this is a log from table 403 * [4/mytest0]: this is use "mytest0", with id 4 * OK-0: it means that the request ended up successfully, with no exception (expected or unexpected). * 169: this is the time taken to process the request (169ms). * d141: this is the total Database time used to process the request (141ms). 4123c3426fa68031dd4dd97a71e1dccfe2d70d90 895 894 2013-06-20T19:58:49Z Sourisdudesert 1 /* Request responses */ wikitext text/x-wiki BGA Studio logs are available directly from your game development interface. Logs allows you to check out what happened recently on server and to debug your game. == BGA request&SQL logs == On this log, you can see: === Your requests === Example: 20/06 21:50:56 [info] [T403] [4/mytest0] /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 Note that the best way to check your Ajax request is to read the [[http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#Input.2FOutput_debugging_section Input/Output section]]. === Request responses === Example: 20/06 21:50:56 [notice] [T403] [4/mytest0] OK-0 169 d141 c8 e0 I9 A158 V0 T0 /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 You can recognize a response because it contains [notice]. Usually, there is one response for each request. Let's details the beginning of the log: * 20/06 21:50:56: the date * [notice] * [T403]: this is a log from table 403 * [4/mytest0]: this is use "mytest0", with id 4 * OK-0: it means that the request ended up successfully, with no exception (expected or unexpected). * 169: this is the time taken to process the request (169ms). * d141: this is the total Database time used to process the request (141ms). 7857032caa340af1ad58d8a4f03e59f814f40b19 896 895 2013-06-20T20:02:52Z Sourisdudesert 1 /* BGA request&SQL logs */ wikitext text/x-wiki BGA Studio logs are available directly from your game development interface. Logs allows you to check out what happened recently on server and to debug your game. == BGA request&SQL logs == This log is useful: * When you want to check what SQL requests has been built during a request. * When you want to debug your PHP code using "self::trace" * When you want to know why a request takes too many time. On this log, you can see: === Your requests === Example: 20/06 21:50:56 [info] [T403] [4/mytest0] /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 Note that the best way to check your Ajax request is to read the [[http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#Input.2FOutput_debugging_section Input/Output section]]. === Request responses === Example: 20/06 21:50:56 [notice] [T403] [4/mytest0] OK-0 169 d141 c8 e0 I9 A158 V0 T0 /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 You can recognize a response because it contains [notice]. Usually, there is one response for each request. Let's details the beginning of the log: * 20/06 21:50:56: the date * [notice] * [T403]: this is a log from table 403 * [4/mytest0]: this is use "mytest0", with id 4 * OK-0: it means that the request ended up successfully, with no exception (expected or unexpected). * 169: this is the time taken to process the request (169ms). * d141: this is the total Database time used to process the request (141ms). === SQL requests === Example: 20/06 21:50:56 [info] [T403] [4/mytest0] 0.26 SELECT player_tokenColor FROM player WHERE player_id ='4' All requests to Database are traced in this log. You can see here the time take by the request (0,26ms). 5fb44e06a4378b1bc27d1ef9de818ff079a6161f 897 896 2013-06-20T20:06:31Z Sourisdudesert 1 /* SQL requests */ wikitext text/x-wiki BGA Studio logs are available directly from your game development interface. Logs allows you to check out what happened recently on server and to debug your game. == BGA request&SQL logs == This log is useful: * When you want to check what SQL requests has been built during a request. * When you want to debug your PHP code using "self::trace" * When you want to know why a request takes too many time. On this log, you can see: === Your requests === Example: 20/06 21:50:56 [info] [T403] [4/mytest0] /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 Note that the best way to check your Ajax request is to read the [[http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#Input.2FOutput_debugging_section Input/Output section]]. === Request responses === Example: 20/06 21:50:56 [notice] [T403] [4/mytest0] OK-0 169 d141 c8 e0 I9 A158 V0 T0 /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 You can recognize a response because it contains [notice]. Usually, there is one response for each request. Let's details the beginning of the log: * 20/06 21:50:56: the date * [notice] * [T403]: this is a log from table 403 * [4/mytest0]: this is use "mytest0", with id 4 * OK-0: it means that the request ended up successfully, with no exception (expected or unexpected). * 169: this is the time taken to process the request (169ms). * d141: this is the total Database time used to process the request (141ms). === SQL requests === Example: 20/06 21:50:56 [info] [T403] [4/mytest0] 0.26 SELECT player_tokenColor FROM player WHERE player_id ='4' All requests to Database are traced in this log. You can see here the time take by the request (0,26ms). === Custom trace === You can use special PHP methods in your PHP code to left some trace in this log: * self::trace( "your message here" ); // Display "your message here" in the log * self::dump( "My variable", $variable_to_dump ); // Display the content of $variable_to_dump in the log 9e994b9737a804e7ab1d1bfdb69c6c00e48a06df 898 897 2013-06-20T20:07:24Z Sourisdudesert 1 wikitext text/x-wiki BGA Studio logs are available directly from your game development interface. Logs allows you to check out what happened recently on server and to debug your game. == BGA request&SQL logs == This log is useful: * When you want to check what SQL requests has been built during a request. * When you want to debug your PHP code using "self::trace" * When you want to know why a request takes too many time. On this log, you can see: === Your requests === Example: 20/06 21:50:56 [info] [T403] [4/mytest0] /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 Note that the best way to check your Ajax request is to read the [[http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#Input.2FOutput_debugging_section Input/Output section]]. === Request responses === Example: 20/06 21:50:56 [notice] [T403] [4/mytest0] OK-0 169 d141 c8 e0 I9 A158 V0 T0 /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 You can recognize a response because it contains [notice]. Usually, there is one response for each request. Let's details the beginning of the log: * 20/06 21:50:56: the date * [notice] * [T403]: this is a log from table 403 * [4/mytest0]: this is use "mytest0", with id 4 * OK-0: it means that the request ended up successfully, with no exception (expected or unexpected). * 169: this is the time taken to process the request (169ms). * d141: this is the total Database time used to process the request (141ms). === SQL requests === Example: 20/06 21:50:56 [info] [T403] [4/mytest0] 0.26 SELECT player_tokenColor FROM player WHERE player_id ='4' All requests to Database are traced in this log. You can see here the time take by the request (0,26ms). === Custom trace === You can use special PHP methods in your PHP code to left some trace in this log: * self::trace( "your message here" ); // Display "your message here" in the log * self::dump( "My variable", $variable_to_dump ); // Display the content of $variable_to_dump in the log == BGA unexpected exceptions logs == 37bc965f13f59e5a37e9b60206ed34bc5ab9d53b 899 898 2013-06-20T20:10:01Z Sourisdudesert 1 /* BGA unexpected exceptions logs */ wikitext text/x-wiki BGA Studio logs are available directly from your game development interface. Logs allows you to check out what happened recently on server and to debug your game. == BGA request&SQL logs == This log is useful: * When you want to check what SQL requests has been built during a request. * When you want to debug your PHP code using "self::trace" * When you want to know why a request takes too many time. On this log, you can see: === Your requests === Example: 20/06 21:50:56 [info] [T403] [4/mytest0] /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 Note that the best way to check your Ajax request is to read the [[http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#Input.2FOutput_debugging_section Input/Output section]]. === Request responses === Example: 20/06 21:50:56 [notice] [T403] [4/mytest0] OK-0 169 d141 c8 e0 I9 A158 V0 T0 /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 You can recognize a response because it contains [notice]. Usually, there is one response for each request. Let's details the beginning of the log: * 20/06 21:50:56: the date * [notice] * [T403]: this is a log from table 403 * [4/mytest0]: this is use "mytest0", with id 4 * OK-0: it means that the request ended up successfully, with no exception (expected or unexpected). * 169: this is the time taken to process the request (169ms). * d141: this is the total Database time used to process the request (141ms). === SQL requests === Example: 20/06 21:50:56 [info] [T403] [4/mytest0] 0.26 SELECT player_tokenColor FROM player WHERE player_id ='4' All requests to Database are traced in this log. You can see here the time take by the request (0,26ms). === Custom trace === You can use special PHP methods in your PHP code to left some trace in this log: * self::trace( "your message here" ); // Display "your message here" in the log * self::dump( "My variable", $variable_to_dump ); // Display the content of $variable_to_dump in the log == BGA unexpected exceptions logs == In this log you can check the last Unexpected exceptions from your game. Exceptions management on PHP side [[http://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Managing_errors_and_exceptions is described here]]. The log displayed the complete stacktrace of the exception, so you can debug it. b302ba731048fb2cebae26604f24b8d7f1941057 Gamehelpseasons 0 43 900 844 2013-06-22T20:25:45Z Charlow 3423 wikitext text/x-wiki Seasons is a game of generating points (crystals) by choosing the correct combination of dice and the activation of card powers. The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be returned to the player on the starting of each cycle. Each player can choose only one die per turn. The effects are as follows: ''Star'' - increase the maximum card player can summon (max 15) ''Elements'' - Gain an energy of the element shown (water, earth, air, fire) ''Numbers'' - Gain the number of Crystals as indicated by the number ''Square card'' - Draw a card ''Dice with frames surrounding'' - Allow user to transmute energy into crystal (depend on which part of the game is at) ''Dots'' - Indicate how fast the marker progresses through the seasons cycle There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There are 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element and allow user to choose a card out of 2 cards (must use with draw card dice). At the end of the game the points are calculated by adding the numbers on each played card and the crystal owned and substracting 5 points for each power card remaining in hand. The player with the most victory points wins. Note: Users need to discard energy immediately if the energy is more than the slots allocated. If a card allows you to summon another card but you have no space for this second card then it (the second card) will be discarded with no refund. == Difficulty levels: == '''Apprentice wizard level''' In order to make the game easier to learn, there are “pre-constructed” sets of nine power cards. Instead of taking step 1 of the first game phase, each player gets one of these sets. '''Magician level''' Only the power cards numbered 1 to 30 are in play. These cards have easy to grasp effects and will allow you to slowly discover the world of Seasons. '''Archmage level''' All 50 kinds of power cards are in play. The cards numbered 31 through 50 have more complex effects than the basic cards, but will allow you to extend the fun of playing by discovering new effects and combinations. 5a76f838e4388603a11a1166cb6bacfaecc16b97 Game interface logic: yourgamename.js 0 88 901 834 2013-06-30T13:34:16Z Een 3 /* Animations */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board" ).play(); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Reversi example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> f6a8e63abe8a7466d9a3479fed629a109b8456ee 902 901 2013-06-30T13:35:10Z Een 3 /* Animations */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ).play(); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onClick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Reversi example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 33ef921054092140ab755e1a5f8911af4ec21d61 Gamehelpelfenland 0 126 903 888 2013-07-06T22:29:06Z Spacediver 718 /* Goal of the game */ wikitext text/x-wiki == Goal of the game == Visiting as many cities as possible in Elfenland over 4 rounds. At the end of the 4th round, the player who collected the most Town Pieces wins. Any players having equal number of Town Pieces are ranked by remaining cards (the more the better). We advise you to play with at least 3 players to best enjoy the game (4 or 5 is even better). A lot of the fun comes from using the Transportation Counters set by other players to optimise one's travels, so the more the merrier! == Round overview == A round is split into phases: # Each player fills his hand up to 8 cards and gets a secret Transportation Counter. # One after another, each player chooses a Transportation Counter from the 5 visible or drawn from the facedown stack, until each player took 3. # One after another, each player chooses must plan a travel road by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to up the cost of traveling on this road from 1 card. # One after another, each player is going to travel from town to town. The current position of a player is shown by the Elf Boot of his color, initially set on the biggest town, Elvenhold. At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter. == Travel rules == Players can travel : * on the roads on which a Transportation Counter has been set * on the rivers * on the lakes. To travel on a road, a river or a lake, the player needs to pay with the cards in hands the cost matching the terrain of the road and the means of transport used. For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (NB: the 'Magic Cloud' Transportation Counter cannot be used to travel in the desert, as it's too hot for a Cloud over there). Also : * To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows). * To cross a lake, you need to pay two 'Raft' cards. * If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type. * If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road). == Variant == In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round. If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there. This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game. '''Have a good game!''' a06379653e76e9da044516d6027676e8ace27ccb 924 903 2013-08-18T05:23:21Z Chazm 3718 /* Goal of the game */ wikitext text/x-wiki == Goal of the game == Visiting as many cities as possible in Elfenland over 4 rounds. At the end of the 4th round, the player who collected the most Town Pieces wins. Any players having an equal number of Town Pieces are ranked by remaining cards (the more the better). We advise you to play with at least 3 players to best enjoy the game (4 or 5 is even better). A lot of the fun comes from using the Transportation Counters set by other players to optimise one's travels, so the more the merrier! == Round overview == A round is split into phases: # Each player fills his hand up to 8 cards and gets a secret Transportation Counter. # One after another, each player chooses a Transportation Counter from the 5 visible or drawn from the facedown stack, until each player took 3. # One after another, each player chooses must plan a travel road by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to up the cost of traveling on this road from 1 card. # One after another, each player is going to travel from town to town. The current position of a player is shown by the Elf Boot of his color, initially set on the biggest town, Elvenhold. At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter. == Travel rules == Players can travel : * on the roads on which a Transportation Counter has been set * on the rivers * on the lakes. To travel on a road, a river or a lake, the player needs to pay with the cards in hands the cost matching the terrain of the road and the means of transport used. For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (NB: the 'Magic Cloud' Transportation Counter cannot be used to travel in the desert, as it's too hot for a Cloud over there). Also : * To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows). * To cross a lake, you need to pay two 'Raft' cards. * If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type. * If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road). == Variant == In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round. If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there. This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game. '''Have a good game!''' 52928b7fae91e13764e651d3e3c77b390c33e891 925 924 2013-08-18T05:33:30Z Chazm 3718 /* Round overview */ wikitext text/x-wiki == Goal of the game == Visiting as many cities as possible in Elfenland over 4 rounds. At the end of the 4th round, the player who collected the most Town Pieces wins. Any players having an equal number of Town Pieces are ranked by remaining cards (the more the better). We advise you to play with at least 3 players to best enjoy the game (4 or 5 is even better). A lot of the fun comes from using the Transportation Counters set by other players to optimise one's travels, so the more the merrier! == Round overview == A round is split into phases: # Each player fills his hand up to 8 cards and gets a secret Transportation Counter. # One after another, each player chooses a Transportation Counter from the 5 visible or draws from the facedown stack, until each player has taken 3. # One after another, each player must plan a travel route by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to increase the cost of travel by an addtional card. # One after another, each player travels from town to town. The current position of a player is indicated by the Elf Boot of his color, initially set on the biggest town, Elvenhold. At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter. == Travel rules == Players can travel : * on the roads on which a Transportation Counter has been set * on the rivers * on the lakes. To travel on a road, a river or a lake, the player needs to pay with the cards in hands the cost matching the terrain of the road and the means of transport used. For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (NB: the 'Magic Cloud' Transportation Counter cannot be used to travel in the desert, as it's too hot for a Cloud over there). Also : * To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows). * To cross a lake, you need to pay two 'Raft' cards. * If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type. * If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road). == Variant == In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round. If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there. This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game. '''Have a good game!''' 604d9ffb19ecc5618c7a2ad55816fe5a2cc215f1 926 925 2013-08-18T05:37:14Z Chazm 3718 /* Travel rules */ wikitext text/x-wiki == Goal of the game == Visiting as many cities as possible in Elfenland over 4 rounds. At the end of the 4th round, the player who collected the most Town Pieces wins. Any players having an equal number of Town Pieces are ranked by remaining cards (the more the better). We advise you to play with at least 3 players to best enjoy the game (4 or 5 is even better). A lot of the fun comes from using the Transportation Counters set by other players to optimise one's travels, so the more the merrier! == Round overview == A round is split into phases: # Each player fills his hand up to 8 cards and gets a secret Transportation Counter. # One after another, each player chooses a Transportation Counter from the 5 visible or draws from the facedown stack, until each player has taken 3. # One after another, each player must plan a travel route by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to increase the cost of travel by an addtional card. # One after another, each player travels from town to town. The current position of a player is indicated by the Elf Boot of his color, initially set on the biggest town, Elvenhold. At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter. == Travel rules == Players can travel : * on the roads on which a Transportation Counter has been set * on the rivers * on the lakes To travel on a road, a river or a lake, the player needs to pay with the cards in hand the cost matching the terrain of the road and the means of transport used. For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (Note: the 'Magic Cloud' Transportation Counter cannot be placed in the desert, as it's too hot for a Cloud there). Also : * To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows). * To cross a lake, you need to pay two 'Raft' cards. * If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type. * If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road). == Variant == In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round. If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there. This variant gives more tactic depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game. '''Have a good game!''' c57cd8daa62a4072f5c756b58bbe2784d44635f7 927 926 2013-08-18T05:38:33Z Chazm 3718 /* Variant */ wikitext text/x-wiki == Goal of the game == Visiting as many cities as possible in Elfenland over 4 rounds. At the end of the 4th round, the player who collected the most Town Pieces wins. Any players having an equal number of Town Pieces are ranked by remaining cards (the more the better). We advise you to play with at least 3 players to best enjoy the game (4 or 5 is even better). A lot of the fun comes from using the Transportation Counters set by other players to optimise one's travels, so the more the merrier! == Round overview == A round is split into phases: # Each player fills his hand up to 8 cards and gets a secret Transportation Counter. # One after another, each player chooses a Transportation Counter from the 5 visible or draws from the facedown stack, until each player has taken 3. # One after another, each player must plan a travel route by laying a Transportation Counter matching the terrain of the chosen road. This phase goes on until each player has passed consecutively. Each player also owns an Obstacle that he can lay down on a Transportation Counter to increase the cost of travel by an addtional card. # One after another, each player travels from town to town. The current position of a player is indicated by the Elf Boot of his color, initially set on the biggest town, Elvenhold. At the end of the round, a player can keep a maximum of 4 cards in hand, and keeps only 1 Transportation counter. == Travel rules == Players can travel : * on the roads on which a Transportation Counter has been set * on the rivers * on the lakes To travel on a road, a river or a lake, the player needs to pay with the cards in hand the cost matching the terrain of the road and the means of transport used. For example, if the Transportation Counter 'Magic Cloud' has been set on a mountain road, one can travel with just one 'Magic Cloud' card. But if it has been set on a forest or plain road, one needs to pay 2 'Magic Cloud' cards to pass (Note: the 'Magic Cloud' Transportation Counter cannot be placed in the desert, as it's too hot for a Cloud there). Also : * To travel a river, you need only 1 'Raft' card to go downriver, but you need 2 to go upriver (look for the small arrows). * To cross a lake, you need to pay two 'Raft' cards. * If an Obstacle has been set on a road, you need to pay 1 more card of the appropriate type. * If you don't have the appropriate cards to travel on a road, you can still pass using a 'Caravan', by paying 3 cards of any type (4 cards if there is an Obstacle on the road). == Variant == In the 'Hometown' variant, each player gets a secret town card at the beginning of the game, telling him which town he has to reach at the end of the 4th round. If he doesn't manage to get there, he'll lose as many points as the remaining distance he has to travel to get there. This variant gives more tactical depth to the game, as you have to plan each round to the best to get the most Town Pieces while making sure to be able to get to your hometown at the end of the game. '''Have a good game!''' 908794728060afee29a7eab7dd4e91cc500b128b Reputation 0 17 904 165 2013-07-09T05:27:59Z Jest phulin 3510 /* Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png */ wikitext text/x-wiki [[Category:Help]] == What is reputation ? == On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance. To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items: * Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png) * % of games you finished * % of games you finished with no clock penalties Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits. == How to increase my reputation / what makes my reputation decrease ? == At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks. * a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player. * a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player. You can only give a single thumb (green or red) to a single player. If your opinion evolved you can click again on a thumb to reflect this change. As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended to leave the game or to expel this player. By nature, opinions are subjectives. There is nothing we can do for you if you receive a for an unfair reason. However, we know by experience that this system has a lot of advantages and give a relevant information. Qn: its unclear if the "> 10% unfavorable" warning is calculated against the number of "thumbs up / thumbs down".. or "total number of unique players played with / thumbs down". Hope the formula is the latter.. as the first formula will raise many more warnings.. more idiots give thumbs down, and are lazier to give thumb up. == Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png == * Be polite! Say at least "hello" and "good luck" at the beginning of the game, and maybe "good game" ("gg") at the end of the game. * When you need some time to think, click on "I would like to think a little" link. * Always stay calm: it's a game. * Don't press your opponent to play if he has some time left. * If you really can't finish the game (this is not supposed to happen...), then say you are sorry and leave the game (don't wait to get expelled) to save your opponents time. Voluntarily disconnecting and conceding victory to the opponent does not cost you reputation like being expelled does. * Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!). * Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation. == What are the consequences of a bad reputation ? == A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you. It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents. 67cf8fc8799861af33ddd3c786489e404d2ed3fb Privacy 0 128 905 2013-07-09T06:22:06Z Een 3 Created page with "To create an account, you need to provide an email, user name and password. You can also complete your player profile with some other data. We store this data. Yep. It would ..." wikitext text/x-wiki To create an account, you need to provide an email, user name and password. You can also complete your player profile with some other data. We store this data. Yep. It would be pretty annoying for you to enter it each time you visit ;) If you are 'internet paranoid' and you never provide any website with accurate personal information, congratulations! You can skip this section. If you are not, congratulations! You can also skip this section which is intended only for 'internet paranoid' people anyway... It has been written for compliance with some social network authentication policy (take your bet, there is only two - oh, wait, if you are reading this you probably know). Well, to be fair, I could have left it empty too, the only check made by said social network being that the page exists. But, what would have been the fun in that? If you are still interested to read on some stuff instead of going straight to playing: * Your password is stored encrypted, but the usual precautionary measures apply. You should use a strong password and not use the same one that for sensitive websites. Some people would say never to use the same password, but this looks like excessive blunt force to the head, except for websites with very sensitive information. Shouldn't be the case on a gaming website, but hey, do as you please. * We don't share your email with third parties without your consent. Your consent may be implicit in some obvious cases (such as if you take part in a contest with prizes from a publisher, as it will be needed for the publisher to contact you to redeem the prize). * Your profile information is visible to other players, as well as your gaming history on the website. So, since anyone can create an account on the site, it should be considered public information. But if you use a pseudonym for your username, it shouldn't be easy to link it to your real identity (in case you would be worried about that). Hope this all sounds reasonable to you, and that you can now enjoy Board Game Arena without second thoughts! Cheers and doughnuts, The admins. 936ac1f56e7544f713799cdf86cc4e3b858babbf The Boss 0 46 906 423 2013-07-10T03:32:08Z Stationary 3106 wikitext text/x-wiki == Goal == At the end of the hand, the player with the most gangsters in the city wins the "city card" that was placed face down at the beginning of the hand. Be the player with the most money at the end of the game! == Description == Each city, except '''Chicago''', has one hidden card underneath it. The rest of the cards are distributed among the players, giving each player information on which card is hidden under each city. Each round, each player: 1) May place gangsters on a city. The large gangsters (Experts) are returned at the end of each round, while the small (Occasionalists) ones are not. After placing the gangsters, you must have more of them than any opponent on that city. 2) Must play a card from your hand, revealing that information about the city. When everybody has 2 cards in their hand, the police card is turned over. If there are 3 police symbols with the same color turned over, the game ends after the hand in progress is finished. When everybody is out of cards, reveal the face down cards. Whoever has the most gangsters on the city 'wins' that face down card. If it is money, it is worth that many points. If it is a gun one of your big gangsters is killed, the bars mean they go to jail for 2 rounds and the red cross sign is hospital for 1 turn. If you get the crossed out man card in Cincinnati you are banned from playing gangsters there the rest of the game. '''Chicago''' Chicago doesn't have a hidden card, instead it is worth one half (rounded down) of the sum of the last cards played from a player's hand on each of the cities to its left, it moves one space right each round. == Beginner Tips == *Give out useless information early and hold on to your gangsters until seeing what your opponents are planning. *If you have the gun for Detroit or Kansas City you KNOW that city will be worth some points. This isn't true for Philadelphia which could still send you to jail. 31c2382f9f02f6aec6f8b1aa93cb206bb8f445ff Gamehelpreversi 0 124 907 868 2013-07-15T21:15:37Z Januszk0 3262 Opis wikitext text/x-wiki Othello znane również pod nazwą Reversi to wciągająca gra logiczna, której korzenie sięgają XVIII wieku. W grę od XIX wieku gra niemal cała Europa. O jej wielkiej popularności zadecydowały proste reguły (prostsze niż warcabów) i bogactwo kombinacyjne dorównujące szachom. Od tych ostatnich gra jest jednak zdecydowanie bardziej dynamiczna. == Zasady gry: == Rozgrywka toczy się na kwadratowej planszy podzielonej na 64 pola (8x8). Każdy z graczy ma dostęp do wspólnego zestawu dwustronnych pionków (zwyczajowo, z jedną stroną białą, a drugą czarną). Gracze na zmianę wykonują ruchy dokładając na planszy pionki w swoim kolorze. Pionki należy układać w taki sposób, aby pomiędzy pionkami gracza (poziomo, pionowo lub na skos) znalazła się jak największa ilość pionków przeciwnika. Po wykonaniu ruchu, wszystkie te pionki zostają przejęte i zmieniają kolor. Jeżeli gracz nie może wykonać dozwolonego przepisami posunięcia, musi pauzować (traci kolejkę). Celem gry jest ułożenie na planszy jak największej ilości pionków, tak aby zamienić pionki przeciwnika na własne. Wygrywa ten z graczy, którego większa liczba pionków znajduje się na planszy po zakończeniu gry. W przypadku równej ilości pionków, gra kończy się remisem. 27f5626440fd71b896475a030a6b7ec0076ee359 908 907 2013-07-15T21:19:16Z Januszk0 3262 Blanked the page wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 909 908 2013-07-15T21:20:35Z Januszk0 3262 wikitext text/x-wiki [http://en.wikipedia.org/wiki/Reversi] fe37062068d582dcb198fb6c0e2dff2371bc9a86 910 909 2013-07-15T21:25:51Z Januszk0 3262 wikitext text/x-wiki [English Rules: Link][http://en.wikipedia.org/wiki/Reversi] 245acab3bf59561ee3167722bfe3b03c5fb3d769 Faq 0 3 911 659 2013-07-18T18:27:30Z Guszty 3271 wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple account and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had a bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. 94dea1133bbc8858fde6d481215ca43bf31342b8 Gamehelpcantstop 0 35 912 757 2013-07-25T17:01:39Z Chaotic iak 3338 wikitext text/x-wiki Can't Stop is a game involving rolling dice and knowing when to stop pushing one's luck. ==Rules== Can't Stop is played with a board consisting of 11 columns, numbered from 2 to 12, four dice, and three temporary pieces. ===Splitting dice=== On a player's turn, they roll the four dice, split it to two groups however they like, then advance a step on each column whose sum is equal to some group of the dice. Examples: * Roll: 3,3,4,4. One can split it to 3,3 and 4,4, advancing a step on each of columns 6 and 8, or 3,4 and 3,4, advancing two steps on column 7. * Roll: 2,3,4,5. One can split it in three ways: 2,3 and 4,5 (columns 5 and 9), 2,4 and 3,5 (columns 6 and 8), or 2,5 and 3,4 (columns 7 and 7). * Roll: 4,4,4,6. There is only one way to split it, 4,4 and 4,6, which means columns 8 and 10. * Roll: 1,1,1,1. There is only one way to split it, 1,1 and 1,1, which means columns 2 and 2. ===Temporary pieces=== In a turn, a player may only advance in three columns. The temporary pieces are to help the player in keeping track their progresses. However, one must make as many moves as possible. Examples: * One hasn't moved at all and rolled 2,3,4,5. They decide to split as 2,3 and 4,5, advancing on columns 5 and 9. This is allowed; they advanced on columns 5,9. They may not choose to advance only on column 5 or only on column 9 because they must perform all moves possible. * One has moved on columns 4 and 5 and rolled 2,3,4,5. They decide to split as 2,3 and 4,5, advancing on columns 5 and 9. This is allowed; they advanced on columns 4,5,9. * One has moved on columns 2 and 3 and rolled 2,3,4,5. They decide to split as 2,3 and 4,5, and so should have advanced on columns 5 and 9. But this is not allowed; it makes them advance on four columns. They must pick either 5 or 9 to advance from. * One has moved on columns 2, 3, and 12 and rolled 2,3,4,5. No matter how they split the dice, they cannot advance. ===Stopping one's turn=== A player keeps their turn until they state to stop or they cannot advance (like the last of the examples above). In the former case, the temporary pieces are made permanent; they will continue from the positions they have now. In the latter case, the temporary pieces are removed; their position is rolled back to before they have started their turn. Examples: * One decides to stop after advancing 3 steps on column 7, 2 steps on column 8, and 1 step on column 9, after previously have advanced 4 steps on column 6 and 3 steps on column 9. Now their position is 4 steps on column 6, 3 steps on column 7, 2 steps on column 8, and 4 steps on column 9. * One advanced 3 steps on column 7, 2 steps on column 8, and 1 step on column 9, after previously have advanced 4 steps on column 6 and 3 steps on column 9, but then cannot advance. Their position is rolled back to only 4 steps on column 6 and 3 steps on column 9. ===Completing a column=== When one decides to stop and they have reached the end of some column, that column is scored for that player and no other player may advance in that column. For example, if column 5 has been scored and one splits a 2,3,4,5 to 2,3 and 4,5, they cannot advance on column 5 because it has been scored. ===Winning condition=== When one scores three columns, they win. ==Strategy== The strategy of the game revolves on knowing when to stop. As one keeps playing, they still have the risk of losing all progress on the turn; stopping will save the progress but gives the other players a turn each. Knowing which is more beneficial helps. Columns with more extreme numbers are less probable (a 2 is only scored by a 1,1 and a 12 is only scored by a 6,6, while a 7 is scored by six pairs of dice), so they have less steps to work on. One's strategy can also revolve on choosing whether to aim for middle columns or extreme columns. b66171fad98a092b617274bc96550af3a344bd51 913 912 2013-08-03T21:30:44Z Theotherk 3645 /* Splitting dice */ wikitext text/x-wiki Can't Stop is a game involving rolling dice and knowing when to stop pushing one's luck. ==Rules== Can't Stop is played with a board consisting of 11 columns, numbered from 2 to 12, four dice, and three temporary pieces. ===Splitting dice=== On a player's turn, they roll the four dice, split the four dice to two groups of two dice however they like, then advance a step on each column whose sum is equal to some group of the dice. Examples: * Roll: 3,3,4,4. One can split it to 3,3 and 4,4, advancing a step on each of columns 6 and 8, or 3,4 and 3,4, advancing two steps on column 7. * Roll: 2,3,4,5. One can split it in three ways: 2,3 and 4,5 (columns 5 and 9), 2,4 and 3,5 (columns 6 and 8), or 2,5 and 3,4 (columns 7 and 7). * Roll: 4,4,4,6. There is only one way to split it, 4,4 and 4,6, which means columns 8 and 10. * Roll: 1,1,1,1. There is only one way to split it, 1,1 and 1,1, which means columns 2 and 2. ===Temporary pieces=== In a turn, a player may only advance in three columns. The temporary pieces are to help the player in keeping track their progresses. However, one must make as many moves as possible. Examples: * One hasn't moved at all and rolled 2,3,4,5. They decide to split as 2,3 and 4,5, advancing on columns 5 and 9. This is allowed; they advanced on columns 5,9. They may not choose to advance only on column 5 or only on column 9 because they must perform all moves possible. * One has moved on columns 4 and 5 and rolled 2,3,4,5. They decide to split as 2,3 and 4,5, advancing on columns 5 and 9. This is allowed; they advanced on columns 4,5,9. * One has moved on columns 2 and 3 and rolled 2,3,4,5. They decide to split as 2,3 and 4,5, and so should have advanced on columns 5 and 9. But this is not allowed; it makes them advance on four columns. They must pick either 5 or 9 to advance from. * One has moved on columns 2, 3, and 12 and rolled 2,3,4,5. No matter how they split the dice, they cannot advance. ===Stopping one's turn=== A player keeps their turn until they state to stop or they cannot advance (like the last of the examples above). In the former case, the temporary pieces are made permanent; they will continue from the positions they have now. In the latter case, the temporary pieces are removed; their position is rolled back to before they have started their turn. Examples: * One decides to stop after advancing 3 steps on column 7, 2 steps on column 8, and 1 step on column 9, after previously have advanced 4 steps on column 6 and 3 steps on column 9. Now their position is 4 steps on column 6, 3 steps on column 7, 2 steps on column 8, and 4 steps on column 9. * One advanced 3 steps on column 7, 2 steps on column 8, and 1 step on column 9, after previously have advanced 4 steps on column 6 and 3 steps on column 9, but then cannot advance. Their position is rolled back to only 4 steps on column 6 and 3 steps on column 9. ===Completing a column=== When one decides to stop and they have reached the end of some column, that column is scored for that player and no other player may advance in that column. For example, if column 5 has been scored and one splits a 2,3,4,5 to 2,3 and 4,5, they cannot advance on column 5 because it has been scored. ===Winning condition=== When one scores three columns, they win. ==Strategy== The strategy of the game revolves on knowing when to stop. As one keeps playing, they still have the risk of losing all progress on the turn; stopping will save the progress but gives the other players a turn each. Knowing which is more beneficial helps. Columns with more extreme numbers are less probable (a 2 is only scored by a 1,1 and a 12 is only scored by a 6,6, while a 7 is scored by six pairs of dice), so they have less steps to work on. One's strategy can also revolve on choosing whether to aim for middle columns or extreme columns. 6de82fa759a9e714493e081febed1557c7456e7f Club Board Game Arena 0 8 914 876 2013-08-08T03:14:53Z Earl of essence 3660 /* Why can't you just have a standard donation system where I can choose any money amount ? */ wikitext text/x-wiki ==Why can't you just have a standard donation system where I can choose any money amount ?== With this "club" system, we try to highlight players who have supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time. Many websites are using a more classic approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena has chosen to set 3 fixed amounts for donations, in order to rely on a bigger number of small donors. ==Is it mandatory to join the club ?== Of course not. You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra : you don't need statistics to play and have fun, don't you ? As a matter of fact, most players are not club members. ==What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif == When you join Board Game Arena, your get a "beginner account" (http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif) for 30 days. This beginner account allow you to view your own ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) for each game. After 30 days, your account becomes a standard '''non member''' account (http://en.boardgamearena.com/theme/img/accounttypes/free.gif). ==What becomes of the money ?== Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost). Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)... A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone ! 325eb81bb9bae3c84de8268c42ea6b12de222a88 915 914 2013-08-08T03:16:02Z Earl of essence 3660 /* Is it mandatory to join the club ? */ wikitext text/x-wiki ==Why can't you just have a standard donation system where I can choose any money amount ?== With this "club" system, we try to highlight players who have supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time. Many websites are using a more classic approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena has chosen to set 3 fixed amounts for donations, in order to rely on a bigger number of small donors. ==Is it mandatory to join the club ?== Of course not. You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra! You don't need statistics to play and have fun, do you? As a matter of fact, most players are not club members. ==What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif == When you join Board Game Arena, your get a "beginner account" (http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif) for 30 days. This beginner account allow you to view your own ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) for each game. After 30 days, your account becomes a standard '''non member''' account (http://en.boardgamearena.com/theme/img/accounttypes/free.gif). ==What becomes of the money ?== Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost). Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)... A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone ! a9b1fab3effc1c29a439f7e5b1b53f26a00cad37 916 915 2013-08-08T03:17:13Z Earl of essence 3660 /* What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif */ wikitext text/x-wiki ==Why can't you just have a standard donation system where I can choose any money amount ?== With this "club" system, we try to highlight players who have supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time. Many websites are using a more classic approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena has chosen to set 3 fixed amounts for donations, in order to rely on a bigger number of small donors. ==Is it mandatory to join the club ?== Of course not. You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra! You don't need statistics to play and have fun, do you? As a matter of fact, most players are not club members. ==What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif == When you join Board Game Arena, you get a "beginner account" (http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif) for 30 days. This beginner account allows you to view your own ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) for each game. After 30 days, your account becomes a standard '''non-member''' account (http://en.boardgamearena.com/theme/img/accounttypes/free.gif). ==What becomes of the money ?== Board Game Arena service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost). Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)... A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone ! b5ffe68707f95aedf17704f721af0a8070495584 917 916 2013-08-08T03:18:25Z Earl of essence 3660 /* What becomes of the money ? */ wikitext text/x-wiki ==Why can't you just have a standard donation system where I can choose any money amount ?== With this "club" system, we try to highlight players who have supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time. Many websites are using a more classic approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena has chosen to set 3 fixed amounts for donations, in order to rely on a bigger number of small donors. ==Is it mandatory to join the club ?== Of course not. You can play for free without any limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra! You don't need statistics to play and have fun, do you? As a matter of fact, most players are not club members. ==What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif == When you join Board Game Arena, you get a "beginner account" (http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif) for 30 days. This beginner account allows you to view your own ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) for each game. After 30 days, your account becomes a standard '''non-member''' account (http://en.boardgamearena.com/theme/img/accounttypes/free.gif). ==What becomes of the money ?== Board Game Arena's service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost). Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)... A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone ! 57edae9e0c931f66c9fd4c5ab1c3ddd8b1f06828 Getting started 0 10 918 23 2013-08-08T03:23:22Z Earl of essence 3660 wikitext text/x-wiki [[Category:Help]] With '''Board Game Arena''' you can play within a few clicks. By choosing "[http://en.boardgamearena.com/#!lobby Play now]" on the left menu, you get a list of game tables waiting for players. You can join a game by clicking on "View table" then "Join game". If you prefer, you can create a new game table: click on the "Launch table" button that corresponds to the game you want to play, and wait for your opponents. Important to know before you start: * It's much better to join a table already created than to create a new one. * For most popular games you will find opponents at any time. For the others, try to connect around peak hour (around 22h CEST) to maximize your chances. * When you start a game you can't leave the table until it ends. If you leave you will receive a penalty which will create difficulties finding opponents later. a757320af56ced6014012dfea845fb0ec8c45592 Gamehelptzolkin 0 129 919 2013-08-09T14:34:28Z Edgar 3667 Created page with " == '''For Each Round''' == - Each player takes their turn, going around the table - On a food day, feed your workers and take your rewards - Advance the Calendar == '''P..." wikitext text/x-wiki == '''For Each Round''' == - Each player takes their turn, going around the table - On a food day, feed your workers and take your rewards - Advance the Calendar == '''Player turn''' == - '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple) - '''Either place workers OR pick up workers''' -- ''Placing workers'': pay for the number of workers you place plus the cost noted next to each placed workers -- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either --- Use the action where your worker was standing --- Use a lower action on the wheel from where your worker was standing(if not standing on a free action space,pay 1 corn for each step back) --- Do nothing. == '''Food Day''' == -'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for. -- For each worker not fed, you lose 3 points -'''Take Rewards''' --''Middle of Age (Brown days)'' --- Receive items shown on the left edge of themples from step you are on and all steps below -- ''End of Age(Teal Days)'' --- Remove all Age 1 buildings and fill spaces with Age 2 buildings/ --- Receive points shown on the right edge of temples for the step you are on. --- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus. == '''Advance the Calendar''' == If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day. Otherwise: - The worker on the Starting Player space returns to the player -- If this person was not the starting player, they take the starting player marker. -- If they were the starting player, the starting player marker is moved to the player on his left - Advance the Tzolk'in Gear one day. - The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears. -- If you use this option. Flip your board to dark side up. -- This does not avoid food days. 4bfacd574a92eebe81d97b17b85b3702ebb652cc 920 919 2013-08-10T02:18:35Z Joseppr 1780 /* Advance the Calendar */ wikitext text/x-wiki == '''For Each Round''' == - Each player takes their turn, going around the table - On a food day, feed your workers and take your rewards - Advance the Calendar == '''Player turn''' == - '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple) - '''Either place workers OR pick up workers''' -- ''Placing workers'': pay for the number of workers you place plus the cost noted next to each placed workers -- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either --- Use the action where your worker was standing --- Use a lower action on the wheel from where your worker was standing(if not standing on a free action space,pay 1 corn for each step back) --- Do nothing. == '''Food Day''' == -'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for. -- For each worker not fed, you lose 3 points -'''Take Rewards''' --''Middle of Age (Brown days)'' --- Receive items shown on the left edge of themples from step you are on and all steps below -- ''End of Age(Teal Days)'' --- Remove all Age 1 buildings and fill spaces with Age 2 buildings/ --- Receive points shown on the right edge of temples for the step you are on. --- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus. == '''Advance the Calendar''' == If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day. Otherwise: - The worker on the Starting Player space returns to the player -- If this person was not the starting player, they take the starting player marker. -- If they were the starting player, the starting player marker is moved to the player on his left - Advance the Tzolk'in Gear one day. - The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears. -- If you use this option, flip your board to dark side up. -- This does not avoid food days. a93481001a7c82b23c85cda088a16424ec014722 921 920 2013-08-10T02:19:54Z Joseppr 1780 /* Food Day */ wikitext text/x-wiki == '''For Each Round''' == - Each player takes their turn, going around the table - On a food day, feed your workers and take your rewards - Advance the Calendar == '''Player turn''' == - '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple) - '''Either place workers OR pick up workers''' -- ''Placing workers'': pay for the number of workers you place plus the cost noted next to each placed workers -- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either --- Use the action where your worker was standing --- Use a lower action on the wheel from where your worker was standing(if not standing on a free action space,pay 1 corn for each step back) --- Do nothing. == '''Food Day''' == -'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for. -- For each worker not fed, you lose 3 points -'''Take Rewards''' --''Middle of Age (Brown days)'' --- Receive items shown on the left edge of themples from step you are on and all steps below -- ''End of Age (Teal Days)'' --- Remove all Age 1 buildings and fill spaces with Age 2 buildings/ --- Receive points shown on the right edge of temples for the step you are on. --- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus. == '''Advance the Calendar''' == If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day. Otherwise: - The worker on the Starting Player space returns to the player -- If this person was not the starting player, they take the starting player marker. -- If they were the starting player, the starting player marker is moved to the player on his left - Advance the Tzolk'in Gear one day. - The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears. -- If you use this option, flip your board to dark side up. -- This does not avoid food days. 492a51ebdd36dc9ecb3fa747a046c5a54b18ca80 922 921 2013-08-10T18:26:35Z Januszk0 3262 wikitext text/x-wiki == '''W każdej rundzie''' == - Gracze rozgrywają swoje tury zgodnie z ruchem wskazówek zegara - W Dniu Żywienia, gracze żywią robotników i otrzymują nagrody - Przestawiają kalendarz == '''Tury graczy''' == - '''Prośba o kukurydzę:''' Jeśli masz 2 lub mniej koszy kukurydzy, można poprosić o kukurydzę, chyba że jesteś na dole wszystkich trzech świątyń. (Odrzuć całą kukurydzę i weź 3 kosze kukurydzy i przejdź o jeden stopień w dół jednej ze świątyń) - '''Wyślij do pracy na kołach dowolną liczbę robotników lub zdejmij dowolną liczbę robotników z kół''' -- ''Wysyłanie robotników do pracy'': Gracz płaci tyle koszów kukurydzy, ile wynosi numer pola akcji na które wysłał robotnika. Płaci się również dodatkowe kosze kukurydzy za każdego dodatkowego robotnika wysłanego w danej turze -- ''Powrót robotników do wioski'': Można wybrać jednego lub więcej z twoich umieszczonych robotników. Dzięki każdemu powracającemu robotnikowi gracz może: --- Wykonać akcję przy której stał robotnik w momencie zdjęcia, --- Wykonać akcję z jednego z pól o niższym numerze na tym samym kole. Za każdy numer różnicy, gracz musi zapłacić 1 kosz kukurydzy, --- Nie robić nic. Gracz zdejmuje tylko robotnika z koła. == '''Dzień Żywienia''' == -'''Żywienie Robotników''' Każdy gracz musi zapłacić 2 kosze kukurydzy za każdego robotnika, którego ma w grze (na kole lub przed sobą. Gracz musi nakarmić, tylu robotników ile jest w stanie. - Za każdego nienakarmionego robotnika, traci 3 punkty zwycięstwa -'''Weź nagrody''' --''W środku epoki (Brązowo-pomarańczowe Dni Żywienia)'' --- Gracze otrzymują nagrody w postaci surowców i kryształowych czaszek, -- ''Koniec epoki (Niebiesko-zielone Dni Żywienia)'' --- Usuń wszystkie budynki epoki 1 i wyłóżcie budynki epoki 2. --- Gracz otrzymuje punkty zwycięstwa wskazane przez aktualnie zajmowany stopień w świątyni. --- Gracz znajdujący się w danej świątyni na najwyższym stopniu spośród wszystkich graczy otrzymuje punkty bonusowe. Określają go liczby widniejące nad każdą świątynią. W przypadku remisu, wszyscy remisujący gracze otrzymują połowę premii. == '''Przestawianie kalendarza''' == Jeśli nie ma robotnika na polu Pierwszeństwa żadnego gracza, należy umieścić 1 kosz kukurydzy na aktualnym zębie kalendarza Tzolk'in i przesunąć go o 1 dzień. W przeciwnym razie: - Robotnik znajdujący się na najwyżej numerowanym polu wraca do gracza -- Jeśli tą osobą nie był Pierwszy Gracz, bierze znacznik Pierwszego Gracza. -- Jeśli gracz zajmujący pole Pierwszeństwa posiada aktualnie znacznik Pierwszego Gracza, przekazuje go graczowi po swojej lewej stronie. - Przestawić kalendarz Tzolk'in o jeden dzień. - Gracz, który umieścił swojego robotnika na polu Pierwszeństwa może zdecydować, aby przesunąć kalendarz o jeden dodatkowy dzień, jeśli jego plansza nie jest obrócona ciemną stroną ku górze i w rezultacie jakiś robotnik nie zostałby zepchnięty z koła (a nie byłby zepchnięty przy obrocie kalendarza o 1 dzień). -- W przypadku skorzystania z tej opcji, należy obrócić swoją planszę ciemną stroną w górę. -- Przesunięcie kalendarza o 2 dni nie powoduje ominięcia Dnia Żywienia. 8021b92dcc87698161db6689bd4b6f24d3444c02 923 922 2013-08-10T18:31:57Z Januszk0 3262 Undo revision 922 by [[Special:Contributions/Januszk0|Januszk0]] ([[User talk:Januszk0|talk]]) wikitext text/x-wiki == '''For Each Round''' == - Each player takes their turn, going around the table - On a food day, feed your workers and take your rewards - Advance the Calendar == '''Player turn''' == - '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple) - '''Either place workers OR pick up workers''' -- ''Placing workers'': pay for the number of workers you place plus the cost noted next to each placed workers -- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either --- Use the action where your worker was standing --- Use a lower action on the wheel from where your worker was standing(if not standing on a free action space,pay 1 corn for each step back) --- Do nothing. == '''Food Day''' == -'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for. -- For each worker not fed, you lose 3 points -'''Take Rewards''' --''Middle of Age (Brown days)'' --- Receive items shown on the left edge of themples from step you are on and all steps below -- ''End of Age (Teal Days)'' --- Remove all Age 1 buildings and fill spaces with Age 2 buildings/ --- Receive points shown on the right edge of temples for the step you are on. --- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus. == '''Advance the Calendar''' == If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day. Otherwise: - The worker on the Starting Player space returns to the player -- If this person was not the starting player, they take the starting player marker. -- If they were the starting player, the starting player marker is moved to the player on his left - Advance the Tzolk'in Gear one day. - The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears. -- If you use this option, flip your board to dark side up. -- This does not avoid food days. 492a51ebdd36dc9ecb3fa747a046c5a54b18ca80 Gamehelpjaipur 0 115 928 792 2013-09-03T06:18:06Z Hofty 3828 wikitext text/x-wiki In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take. On your turn, you take one of three actions: # '''Take''' a single card or all the camels in the face up row. #: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. #: You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) #: The card row is then replenished from the deck so it always has 5 cards at the start of a turn. # '''Trade''' for 2 or more goods cards from the row. #: You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. #: The cards your traded are added to the card row, so it will still have 5 cards. # '''Sell''' cards to earn points. #: You may sell one or more cards to earn points, but all the cards you sell must be the same color. #: If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. #: Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. #: If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). #: The sold goods cards are discarded. The game continues until either: * Three piles of goods tokens are depleted; OR * The card row cannot be replenished. : At that point, players total the points they have on their earned goods tokens and bonus tokens. : In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. : Whichever player earns more points total wins the round. : Tie-breaker, in order: :* Player with more bonus tokens wins the round; :* Player with more goods tokens wins the round; After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game. e52209133c4cf5f83fe7b582a15608cf0196cdbe How to join BGA developer team? 0 83 929 777 2013-09-30T15:58:44Z Sourisdudesert 1 wikitext text/x-wiki Registering on BGA Studio is simple and automatic from: http://en.studio.boardgamearena.com To register, you must agree with [http://en.doc.boardgamearena.com/images/0/02/BGA_TC_Dev_en.pdf ''''terms & conditions' document''']. It's very light, so as to get to the fun part faster. Once registered, you will get by email * one login / password to access files through SFTP * one login / password to access the database (for your games in progress) * ten logins with numeric suffixes from 0 to 9 and a common simple password to test games on the studio website while developing. == Ok, I registered, how to start? == Then... well that's all, you can start! See [[Studio#Great.2C_I.27m_in.21_..._How_should_I_start.3F|Great, I'm in! ... How should I start?]] fb343543e19b566d00dc6f09ee976e3b6833157c Studio 0 49 930 892 2013-09-30T16:00:09Z Sourisdudesert 1 /* What is Board Game Arena Studio? */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the latest information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) BGA Studio website: http://en.studio.boardgamearena.com (original announcement on BGA forum: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973) == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum''']. == BGA Studio documentation == === BGA Studio Framework reference === This part of the documentation focuses on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a &lt;div&gt; element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. * [[Tools and tips of BGA Studio]] * [[Practical debugging]] * [[Studio logs]] * [[Studio back-office]] * [[Studio FAQ]] == BGA Developer team organization == * [[Steps to create a BGA game]] * [[Post-release phase]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] c35e1c0c136bab1179c58e3975449dc99f1e54fe First steps with BGA Studio 0 111 931 775 2013-09-30T16:01:31Z Sourisdudesert 1 /* Connect to your SFTP folder and to the BGA Studio website */ wikitext text/x-wiki == Connect to your SFTP folder and to the BGA Studio website == After your account has been created, you will get by email: * the name of the SFTP server to connect to * your SFTP login and password * ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them. Using this information: # Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as [http://winscp.net/ WinSCP] for example) # Check that your home folder contains : #* One folder for each of the three example games (reversi, hearts, gomoku) #* One folder matching the game you will be developing #* One 'resources.html' file # Open the resources.html file, it contains : #* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file #* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two) #* The URL pointing to the web administration tool for the BGA Studio database. # Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user. == Launch your game and check how to update it == # Find your game in the 'Play now' section and launch a table # Use the 'I want between X and X' players to tick down the maximum players number to the minimum # Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'. # Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save. # Go back to your browser and refresh, check that the game zone has updated. # Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game. # Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image. # Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated. == Commit your changes == Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development. Here is how to go through your first commit: # Go back to your browser tab showing the 'resources.html' file. Click on the URL pointing to the BGA Studio backoffice (do not log out of the BGA Studio website before doing so, or you will get a '''Not authorized''' error message as the authentication is shared); # Click on the 'Sources' menu entry to show the commit form. Enter your game name (under the same form as the name of your game folder: lowercase, no spaces), enter your commit comment (such as 'My first commit') then hit the 'Submit' button; # Check the log for errors, it should end with the following lines: Transmitting file data . Committed revision #revision number#. HAL says: done. NB: you should also commit each time you make a change to your gameoptions.inc.php file or to your stats.inc.php file, as an extra deployment action is needed from us for these files to take effect. Please mention in your commit comment that you need us to deploy those files, or send us an email to ask us to do so. == That's all! == Now you know about the basics of updating your game on BGA Studio and testing your changes. For more information on the specificites of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]]. 586dd4594ea28af9e205f5669a05e5e8aed64c46 932 931 2013-09-30T16:04:24Z Sourisdudesert 1 /* Connect to your SFTP folder and to the BGA Studio website */ wikitext text/x-wiki == Connect to your SFTP folder and to the BGA Studio website == After your account has been created, you will get by email: * the name of the SFTP server to connect to * your SFTP login and password * ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them. Using this information: # Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as [http://winscp.net/ WinSCP] for example) # Check that your home folder contains one folder for each of the three example games (reversi, hearts, gomoku). Each time you create a new game project, one additional folder is added to your "home" folder. # Open the resources.html file, it contains : #* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file #* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two) #* The URL pointing to the web administration tool for the BGA Studio database. # Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user. == Launch your game and check how to update it == # Find your game in the 'Play now' section and launch a table # Use the 'I want between X and X' players to tick down the maximum players number to the minimum # Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'. # Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save. # Go back to your browser and refresh, check that the game zone has updated. # Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game. # Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image. # Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated. == Commit your changes == Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development. Here is how to go through your first commit: # Go back to your browser tab showing the 'resources.html' file. Click on the URL pointing to the BGA Studio backoffice (do not log out of the BGA Studio website before doing so, or you will get a '''Not authorized''' error message as the authentication is shared); # Click on the 'Sources' menu entry to show the commit form. Enter your game name (under the same form as the name of your game folder: lowercase, no spaces), enter your commit comment (such as 'My first commit') then hit the 'Submit' button; # Check the log for errors, it should end with the following lines: Transmitting file data . Committed revision #revision number#. HAL says: done. NB: you should also commit each time you make a change to your gameoptions.inc.php file or to your stats.inc.php file, as an extra deployment action is needed from us for these files to take effect. Please mention in your commit comment that you need us to deploy those files, or send us an email to ask us to do so. == That's all! == Now you know about the basics of updating your game on BGA Studio and testing your changes. For more information on the specificites of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]]. af565310fc4858efe51b38ad1c807020ce5aae1a 933 932 2013-09-30T16:08:02Z Sourisdudesert 1 wikitext text/x-wiki == Connect to the BGA Studio website == Go to BGA Studio website: http://en.studio.boardgamearena.com Choose one of your 10 accounts (ex: myusername0), and login into the website - as you would do for Board Game Arena. == Check projects in progress and available game licences == On the left menu, you can check game projects under development and available game licences. From this point, you can choose what you want to do: * Join an existing project. * Create a new project. * Try to get a licence for a game you don't see in the "available game licences" page (see how-to on "available licences" page). == Connect to your SFTP folder and to the BGA Studio website == After your account has been created, you will get by email: * the name of the SFTP server to connect to * your SFTP login and password * ten BGA Studio logins ending with a numeral ranging from 0 to 9 and the password needed to use them. Using this information: # Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as [http://winscp.net/ WinSCP] for example) # Check that your home folder contains one folder for each of the three example games (reversi, hearts, gomoku). Each time you create a new game project, one additional folder is added to your "home" folder. # Open the resources.html file, it contains : #* The URL pointing to the BGA Studio website (protected with an HTTP Basic authentication scheme, the login and password are also referenced in the 'resources.html' file #* The URL pointing to the BGA Studio backoffice (please note that you must first be logged in on the BGA Studio website to be able to access the backoffice, as the authentication is shared between the two) #* The URL pointing to the web administration tool for the BGA Studio database. # Click on the URL to the BGA Studio website, enter the HTTP Basic credentials when prompted for them (and have your browser conveniently memorize them for you). Then you get to an home page just like the one of the main BGA website. Enter one of your ten BGA studio logins to connect as a user. == Launch your game and check how to update it == # Find your game in the 'Play now' section and launch a table # Use the 'I want between X and X' players to tick down the maximum players number to the minimum # Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'. # Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save. # Go back to your browser and refresh, check that the game zone has updated. # Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game. # Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image. # Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated. == Commit your changes == Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development. Here is how to go through your first commit: # Go back to your browser tab showing the 'resources.html' file. Click on the URL pointing to the BGA Studio backoffice (do not log out of the BGA Studio website before doing so, or you will get a '''Not authorized''' error message as the authentication is shared); # Click on the 'Sources' menu entry to show the commit form. Enter your game name (under the same form as the name of your game folder: lowercase, no spaces), enter your commit comment (such as 'My first commit') then hit the 'Submit' button; # Check the log for errors, it should end with the following lines: Transmitting file data . Committed revision #revision number#. HAL says: done. NB: you should also commit each time you make a change to your gameoptions.inc.php file or to your stats.inc.php file, as an extra deployment action is needed from us for these files to take effect. Please mention in your commit comment that you need us to deploy those files, or send us an email to ask us to do so. == That's all! == Now you know about the basics of updating your game on BGA Studio and testing your changes. For more information on the specificites of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]]. 4db9f5edfea9064f7f121c960821ffa45437f95e 934 933 2013-09-30T16:15:35Z Sourisdudesert 1 wikitext text/x-wiki == Connect to the BGA Studio website == Go to BGA Studio website: http://en.studio.boardgamearena.com Choose one of your 10 accounts (ex: myusername0), and login into the website - as you would do for Board Game Arena. == Check projects in progress and available game licences == On the left menu, you can check game projects under development and available game licences. From this point, you can choose what you want to do: * Join an existing project. * Create a new project. * Try to get a licence for a game you don't see in the "available game licences" page (see how-to on "available licences" page). == Create a new game project == You can do most of projects-related operation from "Control Panel / Manage games". In particular, you can create a new project automatically from there. == Connect to your SFTP folder == From the initial email from the Studion you get: * the name of the SFTP server to connect to * your SFTP login and password Using this information: # Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as [http://winscp.net/ WinSCP] for example) # Check that your home folder contains one folder for each of the three example games (reversi, hearts, gomoku). If you have already created a new game project, one additional folder should be in your "home" folder. == Let's code! == Now, you can try to launch a new game on BGA Studio from the "Play now" menu entry, as you would do on Board Game Arena website. # Find your game in the 'Play now' section and launch a table # Use the 'I want between X and X' players to tick down the maximum players number to the minimum # Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'. # Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save. # Go back to your browser and refresh, check that the game zone has updated. # Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game. # Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image. # Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated. Then you can modify the provided skeleton and begin to develop your game :) == Commit your changes == Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development. You can automatically commit your sources in the repository from "Control Panel / Manage Games / Your games / Commit my modifications". Then: # Enter your commit comment (such as 'My first commit') then hit the 'Submit' button; # Check the log for errors, it should end with the following lines: Transmitting file data . Committed revision #revision number#. HAL says: done. == That's all! == Now you know about the basics of updating your game on BGA Studio and testing your changes. For more information on the specificites of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]]. 84374110062c7881c18ce66a4fc7739285e46ba1 Tutorial reversi 0 57 935 759 2013-09-30T16:16:56Z Sourisdudesert 1 /* Let it look like Reversi */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('../../img/reversi/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "states.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in state.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 5bf435974f89c8abeb2713fa66580b3e0b38160f 936 935 2013-09-30T16:17:31Z Sourisdudesert 1 /* Make the squares appears */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('../../img/reversi/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "states.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in state.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 282982cfad91e05e90904077f85b206b8d802497 937 936 2013-09-30T16:17:49Z Sourisdudesert 1 /* The discs */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for width and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('img/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "states.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in state.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". aa698a8b78cfb8f1505e1f220027722caa717164 Tutorial gomoku 0 73 938 709 2013-09-30T16:19:55Z Sourisdudesert 1 /* Setup the board */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created: [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( 'img/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * In .js->setup() assign the constants to this variable this.gameConstants = gamedatas.constants; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { // At the end of the slide, update the intersection dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'no_stone' ); dojo.addClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'stone_' + notif.args.color ); dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); // We can now destroy the stone since it is now visible through the change in style of the intersection dojo.destroy( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ); })); slide.play(); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( '../../img/gomoku/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, send a score update notification to the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] e99b68b52465537142e09fa28207afcf7ee2c1fb 939 938 2013-09-30T16:21:42Z Sourisdudesert 1 /* Manage states and events */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created: [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( 'img/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * In .js->setup() assign the constants to this variable this.gameConstants = gamedatas.constants; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone ${coordinates}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coordinates' => $this->getFormattedCoordinates($coord_x, $coord_y), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { // At the end of the slide, update the intersection dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'no_stone' ); dojo.addClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'stone_' + notif.args.color ); dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); // We can now destroy the stone since it is now visible through the change in style of the intersection dojo.destroy( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ); })); slide.play(); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( 'img/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, send a score update notification to the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 5b632d978467043e546b8e53050a67a7c86201ad Studio FAQ 0 53 940 831 2013-09-30T16:22:43Z Sourisdudesert 1 /* I can't access the Studio back-office, I get a 'Not authorized' error message? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the [http://winscp.net/ WinSCP client]. == I can't edit the files in my game directory, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == I don't know the name to use to commit my game, what name should I use? == The game name for committing is the name of the game in lower case and without spaces or special characters (ex: puertorico). It is the same name as the name used for the game folder in your SFTP access. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. Check [[Translations]] to see how to make your game translatable. == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == When you modify these 2 files, you need to deploy the update from your BGA backoffice page. == Should I use images free from copyright? == If you are developing a game in the public domain, yes (or you can make your own if you feel it's better). If you are developing a game for which we have a licence, we will usually provide art files from the publisher. 4f4bdecc8aefcd03cb2a55b3275da02813136c01 941 940 2013-09-30T16:22:51Z Sourisdudesert 1 /* I don't know the name to use to commit my game, what name should I use? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the [http://winscp.net/ WinSCP client]. == I can't edit the files in my game directory, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == BGA administrators will translate the game in French before the game release. After the game release, the collaborative translation interface can be used to translate into other languages. Check [[Translations]] to see how to make your game translatable. == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == When you modify these 2 files, you need to deploy the update from your BGA backoffice page. == Should I use images free from copyright? == If you are developing a game in the public domain, yes (or you can make your own if you feel it's better). If you are developing a game for which we have a licence, we will usually provide art files from the publisher. 9702d3fd8ae2fc57912a7b38c8fb3fb1f582d33d 942 941 2013-09-30T16:23:26Z Sourisdudesert 1 /* How can I provide translation in my language? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the [http://winscp.net/ WinSCP client]. == I can't edit the files in my game directory, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == The community will translate the game in all language after the game release with the collaborative translation interface can be used to translate into other languages. Check [[Translations]] to see how to make your game translatable. == I updated the images in the 'img' folder of my game, but they don't show? == On BGA Studio, there is the gameserver you are developing on, and the main site server that is used to launch the games. The game icon, box and the publisher logo are hosted on the main site server, so they are not immediately available when you modify them on the gameserver. To deploy them on the main site, you have to use the [[Studio back-office]] to do a commit. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == When you modify these 2 files, you need to deploy the update from your BGA backoffice page. == Should I use images free from copyright? == If you are developing a game in the public domain, yes (or you can make your own if you feel it's better). If you are developing a game for which we have a licence, we will usually provide art files from the publisher. 8ebb6ee7fdf24f8caa59262dab1786dcc53fcf91 943 942 2013-09-30T16:25:25Z Sourisdudesert 1 /* I updated the images in the 'img' folder of my game, but they don't show? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the [http://winscp.net/ WinSCP client]. == I can't edit the files in my game directory, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == The community will translate the game in all language after the game release with the collaborative translation interface can be used to translate into other languages. Check [[Translations]] to see how to make your game translatable. == I updated the images in the 'img' folder of my game, but they don't show? == '''Concerning game_box.png, game_icon.png and publisher.png''': You must use "Reload game box image" function from "Control Panel / Manage Games / Your game" to make your change visible. '''Concerning other images''': Other images used during the game are immediately available without any action. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics, but they don't show? == When you modify these 2 files, you need to deploy the update from your BGA backoffice page. == Should I use images free from copyright? == If you are developing a game in the public domain, yes (or you can make your own if you feel it's better). If you are developing a game for which we have a licence, we will usually provide art files from the publisher. 0866a26dcc172d82d512489bf6e1883e7573515e 944 943 2013-09-30T16:26:51Z Sourisdudesert 1 /* I added some game options / some game statistics, but they don't show? */ wikitext text/x-wiki This is a place where we will collect and answer frequently asked questions. == What should I use to access the files through SFTP? == There is a lot of tools to do that. Use the one you are the most comfortable with. On Linux Gnome, you can for example use the 'Connect to server' function of the Nautilus file management system, or use sshfs. On Windows, there is for example the [http://winscp.net/ WinSCP client]. == I can't edit the files in my game directory, it looks like they are readonly. What's happening? == Maybe there is a maintenance operation underway. If you don't get access back after some time (say one or two hours), please send us a mail to check. == What is the working language on BGA studio? == Working language is '''English'''. Variables and functions must be named with English words. Comments must be written in English. Game interface strings and game logs must be written in English. == How can I provide translation in my language? == The community will translate the game in all language after the game release with the collaborative translation interface can be used to translate into other languages. Check [[Translations]] to see how to make your game translatable. == I updated the images in the 'img' folder of my game, but they don't show? == '''Concerning game_box.png, game_icon.png and publisher.png''': You must use "Reload game box image" function from "Control Panel / Manage Games / Your game" to make your change visible. '''Concerning other images''': Other images used during the game are immediately available without any action. If the images still don't show after that, please try emptying your browser cache and reloading the page. == I added some game options / some game statistics / some game infos but they don't show? == When you modify one of these 3 files, you need to use the corresponding update action from "Control Panel / Manage Games / Your Game" in order we can take this information into account. == Should I use images free from copyright? == If you are developing a game in the public domain, yes (or you can make your own if you feel it's better). If you are developing a game for which we have a licence, we will usually provide art files from the publisher. 204f89bb29ebe846f92df7fb2465c3fbc5525394 Studio file reference 0 54 945 454 2013-09-30T16:29:24Z Sourisdudesert 1 wikitext text/x-wiki This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment. === 'img' directory === This directory contains the images for your game (the game art). === gameinfos.inc.php === In this file you describe the meta-information for your game: game name, publisher name, number of player, game categories, etc... === dbmodel.sql === File for creating specific database tables that you will need to persist data during the game (for example a table for cards). === gameoptions.inc.php === File for describing your game options (= game variants) === <gamename>.action.php === File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions. === <gamename>.css === CSS styles specific to your game. === <gamename>.game.php === This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. === <gamename>.js === This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. === <gamename>.view.php and <gamename>_<gamename>.tpl === Files used to set up the page layout ('view') for the game. === material.inc.php === File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants. === states.inc.php === This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). === stats.inc.php === File used to list statistics that you want to update during the game to be presented to players at the end of the game. 16fa2ec038a841941fbc7955f6cd2d40702d2ba7 Main game logic: yourgamename.game.php 0 86 946 837 2013-09-30T16:32:23Z Sourisdudesert 1 /* Manage player scores and Tie breaker */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. c7a1c116b0b88b77bab55c2bf6aa0b5fd6243a66 Game interface stylesheet: yourgamename.css 0 96 947 832 2013-09-30T16:33:26Z Sourisdudesert 1 wikitext text/x-wiki This is the CSS stylesheet of your game User Interface. Styles defined on this file will be applied to the HTML elements you define in your HTML template (yourgame_yourgame.tpl), and to HTML elements you create dynamically with Javascript. Usually, you are using CSS to: 1°) define the overall layout of your game (ex: place the board on the top left, place player's hand beside, place the deck on the right, ...). 2°) create your CSS-sprites: All images of your games should be gathered into a small number of image files. Then, using background-image and background-position CSS properties, you create HTML blocks that can display these images correctly. Example: <pre> Example of CSS sprites (a black token and a white token, 20x20px each, embedded in the same "tokens.png" 40x20px image): .white_token { background-image: url('img/tokens.png'); background-position: 0px 0px; } .black_token { background-image: url('img/tokens.png'); background-position: -20px 0px; } .token { width: 20px; height: 20px; background-repeat: none; } </pre> 3°) ... anything else: It is really easy to add and remove CSS classes dynamically from your Javascript with dojo.addClass and dojo.removeClass. It is also easy to check if an element has a class (dojo.hasClass) or to get all elements with a specific class (dojo.query). This is why, very often, using CSS classes for the logic of your user interface allow you to do complex thing easily. Note: on the production platform, this file will be compressed and comments will be removed. Consequently, don't hesitate to put as many comments as necessary. Important: ALL the CSS directives for your game must be included in this CSS file. You can't create additional CSS files and import them. == Warning: using Z-index == You may use z-index CSS property in your game interface, but you should pay attention to the following: BGA dialogs are displayed with a z-index of 950. If you want to use z-index safely, you should use value '''lower than 900'''. About z-index: don't forget that if you are using a z-index, your element will be displayed above all elements that do not have a z-index. So it's no use to have big z-index values: 1 is enough most of the time :) == spectatorMode == When a spectator (= a player that is not part of the game) is viewing a game, the BGA framework add the CSS class "spectatorMode" to the wrapping HTML tag of your game. This way, if you want to apply a special style to some elements of your game for spectators, you can do this in your CSS: <pre> .spectatorMode #your_element_id { /* your special style */ } </pre> The most common usage of this is to hide some elements to spectators. For example, to hide "my hand" elements: <pre> .spectatorMode #my_hand { display: none; } </pre> d2ecdabf8bbe79bc9de1af33a714ff292cf0cc2d Game art: img directory 0 89 948 458 2013-09-30T16:35:56Z Sourisdudesert 1 /* Images loading */ wikitext text/x-wiki == Requested images == The following images are requested by BGA: ;game_box.png * It is displayed on the main site on the game description page and when creating a table (280x280 px). * It should be an image of a physical copy of the game box as it appears in an online shop. * It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game. * The background of the image must be transparent. ;game_icon.png * It is the icon displayed in the lists of games and tables (50x50 px). * This one should not be transparent, and shouldn't have a border (a black border will be add by BGA). * The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title). ;publisher.png * It is the logo of the publisher of the game, displayed on the game description page. * The width must be 150 px. The height can be anything. The image could be transparent. ;publisher2.png (optional) * If the game has been co-published by 2 publishers, you should upload a second image named "publisher2.png" (same characteristic than the first one). == Game art == You must upload in img directory all images of your game interface. === Images loading === '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. Note that you can tune the way images are loaded with Javascript method "dontPreloadImage" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]). === Images format === You can use 3 image format while building your game interface: ;jpg images should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load. ;png images should be used for transparent images. ;gif images can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful. === Use CSS Sprites === To limit the number of images load and make the game load faster, you must use CSS sprites, ie you must gather several images in a single one. To learn more on CSS Sprites: * [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites (W3C documentation)]. * [[Game interface stylesheet: yourgamename.css]] c375cbd06f058de2b6a7055ff948b6cc493d0705 949 948 2013-09-30T16:37:28Z Sourisdudesert 1 /* Requested images */ wikitext text/x-wiki == Requested images == The following images are requested by BGA: ;game_box.png * It is displayed on the main site on the game description page and when creating a table (280x280 px). * It should be an image of a physical copy of the game box as it appears in an online shop. * It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game. * The background of the image must be transparent. ;game_icon.png * It is the icon displayed in the lists of games and tables (50x50 px). * This one should not be transparent, and shouldn't have a border (a black border will be add by BGA). * The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title). ;publisher.png * It is the logo of the publisher of the game, displayed on the game description page. * The width must be 150 px. The height can be anything. The image could be transparent. ;publisher2.png (optional) * If the game has been co-published by 2 publishers, you should upload a second image named "publisher2.png" (same characteristic than the first one). '''Important''': when you modify these images, you MUST click on "Reload game box image" from the Control Panel in order your update can be taken into account. == Game art == You must upload in img directory all images of your game interface. === Images loading === '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. Note that you can tune the way images are loaded with Javascript method "dontPreloadImage" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]). === Images format === You can use 3 image format while building your game interface: ;jpg images should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load. ;png images should be used for transparent images. ;gif images can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful. === Use CSS Sprites === To limit the number of images load and make the game load faster, you must use CSS sprites, ie you must gather several images in a single one. To learn more on CSS Sprites: * [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites (W3C documentation)]. * [[Game interface stylesheet: yourgamename.css]] 63dfdacfb94b2035891ea1876834814a7accb371 Game art: img directory 0 89 950 949 2013-09-30T16:37:41Z Sourisdudesert 1 wikitext text/x-wiki == Requested images == The following images are requested by BGA: ;game_box.png * It is displayed on the main site on the game description page and when creating a table (280x280 px). * It should be an image of a physical copy of the game box as it appears in an online shop. * It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game. * The background of the image must be transparent. ;game_icon.png * It is the icon displayed in the lists of games and tables (50x50 px). * This one should not be transparent, and shouldn't have a border (a black border will be add by BGA). * The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title). ;publisher.png * It is the logo of the publisher of the game, displayed on the game description page. * The width must be 150 px. The height can be anything. The image could be transparent. ;publisher2.png (optional) * If the game has been co-published by 2 publishers, you should upload a second image named "publisher2.png" (same characteristic than the first one). '''Important''': when you modify these images, you MUST click on "Reload game box image" from the Control Panel in order your update can be taken into account. == Game art == You must upload in img directory all images of your game interface. === Images loading === '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. Note that you can tune the way images are loaded with Javascript method "dontPreloadImage" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]). === Images format === You can use 3 image format while building your game interface: ;jpg images should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load. ;png images should be used for transparent images. ;gif images can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful. === Use CSS Sprites === To limit the number of images load and make the game load faster, you must use CSS sprites, ie you must gather several images in a single one. To learn more on CSS Sprites: * [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites (W3C documentation)]. * [[Game interface stylesheet: yourgamename.css]] 40266cef396b2576bf69a369b35f066d285ba3c9 986 950 2013-10-20T20:23:41Z Sourisdudesert 1 /* Requested images */ wikitext text/x-wiki == Requested images == The following images are requested by BGA: ;game_box.png * It is displayed on the main site on the game description page and when creating a table (280x280 px). * It should be a 3D image of a physical copy of the game box as it appears in an online shop. * It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game. * The background of the image must be transparent. * If you don't have a 3D version of the game box, you can use the following website to create one: http://www.3d-pack.com/ ;game_icon.png * It is the icon displayed in the lists of games and tables (50x50 px). * This one should not be transparent, and shouldn't have a border (a black border will be add by BGA). * The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title). ;publisher.png * It is the logo of the publisher of the game, displayed on the game description page. * The width must be 150 px. The height can be anything. The image could be transparent. ;publisher2.png (optional) * If the game has been co-published by 2 publishers, you should upload a second image named "publisher2.png" (same characteristic than the first one). '''Important''': when you modify these images, you MUST click on "Reload game box image" from the Control Panel in order your update can be taken into account. == Game art == You must upload in img directory all images of your game interface. === Images loading === '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. Note that you can tune the way images are loaded with Javascript method "dontPreloadImage" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]). === Images format === You can use 3 image format while building your game interface: ;jpg images should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load. ;png images should be used for transparent images. ;gif images can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful. === Use CSS Sprites === To limit the number of images load and make the game load faster, you must use CSS sprites, ie you must gather several images in a single one. To learn more on CSS Sprites: * [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites (W3C documentation)]. * [[Game interface stylesheet: yourgamename.css]] a3689edf2cf06b2f1687bc4d17adaeaf8a23ff3b Studio 0 49 951 930 2013-09-30T16:39:22Z Sourisdudesert 1 /* Other components */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the latest information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) BGA Studio website: http://en.studio.boardgamearena.com (original announcement on BGA forum: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973) == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum''']. == BGA Studio documentation == === BGA Studio Framework reference === This part of the documentation focuses on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game meta-information: gameinfos.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a &lt;div&gt; element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. * [[Tools and tips of BGA Studio]] * [[Practical debugging]] * [[Studio logs]] * [[Studio back-office]] * [[Studio FAQ]] == BGA Developer team organization == * [[Steps to create a BGA game]] * [[Post-release phase]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] b535d7773a8c8fd1bca0347173a6b7d9be556f76 956 951 2013-09-30T17:00:44Z Sourisdudesert 1 /* BGA Studio user guide */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the latest information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) BGA Studio website: http://en.studio.boardgamearena.com (original announcement on BGA forum: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973) == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum''']. == BGA Studio documentation == === BGA Studio Framework reference === This part of the documentation focuses on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game meta-information: gameinfos.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a &lt;div&gt; element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. * [[Tools and tips of BGA Studio]] * [[Practical debugging]] * [[Studio logs]] * [[Studio FAQ]] == BGA Developer team organization == * [[Steps to create a BGA game]] * [[Post-release phase]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] ac77cc3aebc248727c5d63ba7c05bcfed8a8a923 Game meta-information: gameinfos.inc.php 0 130 952 2013-09-30T16:45:33Z Sourisdudesert 1 Created page with " From this file, you can edit the various meta-information of your game. Once you modified the file, don't forget to click on "Reload game informations" from the Control Pane..." wikitext text/x-wiki From this file, you can edit the various meta-information of your game. Once you modified the file, don't forget to click on "Reload game informations" from the Control Panel in order in can be taken into account. Most information provided in this file are self-explainable. Some information, though: * You are not allowed to set the "is_beta" to 0 before the game has been released on BGA and stabilized. * "fast/medium/slow_additional_time": please set high values here: after the game has been released, we will lower these value to match the real game duration. * "players": during the first step of development of a game, you'd better allow the "1 player" configuration: much easy to start/stop a game this way. * suggest_player_number / not_recommend_player_number: don't specify anything here if there is no configuration that is REALLY better/worst than another one. You can check player's poll on BoardGameGeek game page if you have any doubt. a7f2e3b93ea9584d908256fad7ce012a25fbc445 953 952 2013-09-30T16:53:46Z Sourisdudesert 1 wikitext text/x-wiki From this file, you can edit the various meta-information of your game. Once you modified the file, don't forget to click on "Reload game informations" from the Control Panel in order in can be taken into account. Most information provided in this file are self-explainable. Some information, though: * You are not allowed to set the "'''is_beta'''" to 0 before the game has been released on BGA and stabilized. * "'''fast/medium/slow_additional_time'''": please set high values here: after the game has been released, we will lower these value to match the real game duration. * "'''players'''": during the first step of development of a game, you'd better allow the "1 player" configuration: much easy to start/stop a game this way. * '''suggest_player_number''' / '''not_recommend_player_number''': don't specify anything here if there is no configuration that is REALLY better/worst than another one. You can check player's poll on BoardGameGeek game page if you have any doubt. == Tags == Any number of '''Tags''' can be attribute to your game. Tags are useful to place your game in the correct place and to give a good quick overview of what the game is about to players. Main game category (you MUST specify one tag AND ONLY ONE from this category): * 1: Abstract game * 2: Casual games * 3: For regular players * 4: For core gamers Other tags (you can specify any numbers of tags): * 10: Short game (<10 minutes) * 11: Medium length game (10 minutes to 30 minutes) * 12: Long game (>30mn) * 20: Awarded game (Win a prestigious award) * 22: Prototype (This game has not been published yet) * 23: Classic (This game is a classic from Public Domain) * 30: 2 players (2p game / best with 2 players) * 100: Fantasy theme * 101: Science Fiction them * 102: Historical theme * 103: Adventure * 104: Exploration * 105: Conquest * 106: Building * 200: Card game (Cards plays a central role in this game) * 201: Dice * 202: Solo game * 203: Worker placement * 204: Hand management * 205: Bluff * 206: Tile placement * 207: Combinations * 208: Majority * 209: Race * 210: Collection b7adfde2045949c9bb7e966a50dc3a89a4321342 976 953 2013-10-07T16:25:29Z Sourisdudesert 1 wikitext text/x-wiki From this file, you can edit the various meta-information of your game. Once you modified the file, don't forget to click on "Reload game informations" from the Control Panel in order in can be taken into account. Most information provided in this file are self-explainable. Some information, though: * You are not allowed to set the "'''is_beta'''" to 0 before the game has been released on BGA and stabilized. * "'''fast/medium/slow_additional_time'''": please set high values here: after the game has been released, we will lower these value to match the real game duration. * "'''players'''": during the first step of development of a game, you'd better allow the "1 player" configuration: much easy to start/stop a game this way. * '''suggest_player_number''' / '''not_recommend_player_number''': don't specify anything here if there is no configuration that is REALLY better/worst than another one. You can check player's poll on BoardGameGeek game page if you have any doubt. == Tags == Any number of '''Tags''' can be attribute to your game. Tags are useful to place your game in the correct place and to give a good quick overview of what the game is about to players. Main game category (you MUST specify one tag AND ONLY ONE from this category): * 1: Abstract game * 2: Casual games * 3: For regular players * 4: For core gamers Other tags (you can specify any numbers of tags): * 10: Short game (<10 minutes) * 11: Medium length game (10 minutes to 30 minutes) * 12: Long game (>30mn) * 20: Awarded game (Win a prestigious award) (the game must have been at the '''first''' place of one the [http://boardgamegeek.com/wiki/page/Gaming_Industry_Awards# following major awards list]). * 22: Prototype (This game has not been published yet) * 23: Classic (This game is a classic from Public Domain) * 30: 2 players (2p game / best with 2 players) * 100: Fantasy theme * 101: Science Fiction them * 102: Historical theme * 103: Adventure * 104: Exploration * 105: Conquest * 106: Building * 200: Card game (Cards plays a central role in this game) * 201: Dice * 202: Solo game * 203: Worker placement * 204: Hand management * 205: Bluff * 206: Tile placement * 207: Combinations * 208: Majority * 209: Race * 210: Collection 9a707a842ac57ac98cd686c8adb1c31d424af888 Stock 0 97 954 731 2013-09-30T16:54:40Z Sourisdudesert 1 /* Using stock: a simple example */ wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. At first, don't forget to add "ebg/stock" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <==== HERE ], </pre> The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: * type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. * weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted). * image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_themeurl+'img/your_game_name/yourimage.png' </pre> * image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method. '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. '''onItemCreate''' Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it. Complete example: <pre> // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item: this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); (...) // And here is our "setupNewCard": setupNewCard: function( card_div, card_type_id, card_id ) { // Add a special tooltip on the card: this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' ); // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type // Add some custom HTML content INSIDE the Stock item: dojo.place( this.format_block( 'jstpl_my_card_content', { .... } ), card_div.id ); } </pre> == Tips when adding/removing items to/from Stock components == The usual way is the following: '''Situation A''': When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from. '''Situation B''': When you add a card to a stock item, and this card is coming from another stock: * on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48". * then, remove the source item with "removeFromStockById". (note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide). '''Situation C''': When you move a card from a stock item to something that is not a stock item: * insert the card as a classic HTML template (dojo.place / this.format_block). * place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above). * slide it to its new position with "this.slideToObject" * remove the card from the Stock item with "removeFromStockById". Using the methods above, your cards should slided to, from and between your Stock controls smoothly 01488763215a10369fb58c28d5d29f666d3df21a 955 954 2013-09-30T16:55:31Z Sourisdudesert 1 /* Complete stock component reference */ wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. At first, don't forget to add "ebg/stock" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <==== HERE ], </pre> The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: * type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. * weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted). * image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_gamethemeurl+'img/yourimage.png' </pre> * image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method. '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. '''onItemCreate''' Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it. Complete example: <pre> // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item: this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); (...) // And here is our "setupNewCard": setupNewCard: function( card_div, card_type_id, card_id ) { // Add a special tooltip on the card: this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' ); // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type // Add some custom HTML content INSIDE the Stock item: dojo.place( this.format_block( 'jstpl_my_card_content', { .... } ), card_div.id ); } </pre> == Tips when adding/removing items to/from Stock components == The usual way is the following: '''Situation A''': When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from. '''Situation B''': When you add a card to a stock item, and this card is coming from another stock: * on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48". * then, remove the source item with "removeFromStockById". (note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide). '''Situation C''': When you move a card from a stock item to something that is not a stock item: * insert the card as a classic HTML template (dojo.place / this.format_block). * place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above). * slide it to its new position with "this.slideToObject" * remove the card from the Stock item with "removeFromStockById". Using the methods above, your cards should slided to, from and between your Stock controls smoothly 84276d4edcefbc9680bc48c07d1d64a51b57518e Steps to create a BGA game 0 117 957 809 2013-09-30T17:04:00Z Sourisdudesert 1 wikitext text/x-wiki Here's a summary of the different steps you would follow when developing a game with BGA Studio. {| class="wikitable" |- ! Step !! How to reach this ste?p !! What happened during the step? |- | Initial || [[How to join BGA developer team?]] || You can choose to join an existing team / create a new project |- | Assigned || You choosed a game || You can start the development of the game |- | Pre-alpha || You've started to write some piece of code || You develop the game. During this phase, we can assist you with the framework and give you some pieces of advice. |- | Alpha || You tell us that your development is finished || "BGA review": we are reviewing your game and check if it respects [http://fr.slideshare.net/boardgamearena/bga-studio-guidelines BGA guidelines]. If not, we will ask you (and help you) to fix them. |- | Private beta || We give a "go" || "Publisher review": On preproduction platform, the publisher, the designer, we and you can test the game together and separately. We help you to take into account remarks from the publisher and the designer. |- | Public beta || The adaptation is approved by the publiher || We find together a good launch date for the game, we announce the game on BGA news, and then player can start to play! During the first days, it is common that some bugs are reported by players, and you can fix them following the instructions in [[Post-release phase]]. |- | Gold || The game is stable on BGA || Congrats! You can still modify and optimize things following the instructions in [[Post-release phase]]. |} 3057282ef1dc5e90cca44ca7d9c29442ffdfe22d Post-release phase 0 118 958 825 2013-09-30T17:10:52Z Sourisdudesert 1 wikitext text/x-wiki Your game is now on BGA: congrats! But what happened when there are some bugs to fix or when you want to optimize something? Don't be afraid: you're still allowed to modify your game. You just have to pay attention to the points below. == Bugs reporting == Bugs are reported in the [http://forum.boardgamearena.com/viewforum.php?f=4 BGA bugs forum]. During days after your game has been published and from time to time, please have a look at it to check if everything is fine. == How to submit changes? == There is 3 (short) steps to make your changes visible on BGA (from your Control Panel): * Commit your changes. * Build a new version (don't forget to do a successful commit BEFORE your build). * Deploy your new version in production. == What can be modified after release? == Everything can be modified. BUT, some items requires a special attention, and you must inform us in some cases: ===Changes that breaks the games in progress=== Some changes will break the games in progress at the moment the release/the hotfix will be performed. Each time you make a change, you should ask you the question "it is safe to make this change in a game in progress", and if the answer is "no" you have to inform us. Example of changes that break the games in progress: * Changes in the database schema of the game (dbmodel.sql). * New global variable or game option accessed during the game (if it's only used during setup, it should be safe). * New statistic (it won't be initialized properly, so it's going to crash the game). * Change ID of existing game states (adding new game states is fine). Of course, as a rule of thumb, you should avoid to introduce changes that break a game in progress. Sometimes however, you do not have any other choice. In this case: * Try to group all your updates in one version, thus we won't have to block your game several times. * Tell us explicitly that you introduce some update that can break games in progress so we can block the game during a short time. Note: in the near future, we will introduce the possibility for you to block/unblock a game directly from your Control Panel in order to perform all the process by yourself. === Updating Statistics === You should be careful when updating a statistics: * If you want to add a new statistics, please refer to the paragraph above ("changes that breaks the games in progress"). * If you want to update a statistic, please update it and do not remove/create another one. Otherwise, the statistic won't keep the same ID and players will lost all the historical statistics data. * If your game is published on BGA, please don't remove any statistics (historical data will be lost). === Updating string to be translated === When you update a string that has been marked to be translatable, please keep in mind that all current translations done by the BGA community will be lost. Consequently, when you are about to modify a string to be translated (after release), please ask you the following questions: * Is it just an English misspelling? In this case, it is better to fix the English translation of the string than the original string to be translated. * Has the meaning of the string changed? If yes, you HAVE to change the original string in order to invalidate all translations that has been done already. * Is there a similar string already used elsewhere in my game? In this case, you'd better use it again to enjoy immediately all translations already available. ===Major changes=== If you do some major changes to your game like: * Introducing a new expansion. * Major code rewriting/refactoring. ... please tell us. In this case, we can: * Make your game back from "gold" to "public beta", to incite player to report bugs. * And eventually, publish a news about it :) 860172b542fdcbafd19c16c6a60b8007a7c77266 BGA Game licenses 0 131 959 2013-09-30T19:38:22Z Sourisdudesert 1 Created page with " == What is a "licence" == Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this boar..." wikitext text/x-wiki == What is a "licence" == Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website. == Are all games on BGA licenced by their respective right owners? == Yes. == What if I start developing a game that is not on the list below? == We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process. Exception: games on the public domain are of course not concerned. == Wow, I WANT to develop a game on this list! == Cool :) But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project? == What has to be done to add a game on this list? == The right owners has to give an licence/authorization to BGA. Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract. Important: you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below). == Why all best-sellers games I love are not on that list? == As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA. So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this". We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-. == I want my prototype/unpublished game on BGA == You should take into account the fol == What if I really want to develop a particular game that is NOT on the list below? == This is the most asked question, to please follow the instructions: 0: In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it? Continue to 1. 1: At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher. To find the original publisher: _ check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish). _ check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time. _ very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher. Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome. Continue to 2 2: Read the publisher list below to check if BGA already work with this publisher. If YES, continue to 3. If NO, continue to 4. However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone. 3: Is there already a game licenced by this publisher that has to be developed? If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another. If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop. If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization! 4: We never worked with this publisher before. If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :) If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation. Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA. 695cb0256a099b6554c86258e0822172848a611f 960 959 2013-09-30T19:38:48Z Sourisdudesert 1 /* What if I start developing a game that is not on the list below? */ wikitext text/x-wiki == What is a "licence" == Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website. == Are all games on BGA licenced by their respective right owners? == Yes. == What if I start developing a game that is not on the "Available licences"? == We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process. Exception: games on the public domain are of course not concerned. == Wow, I WANT to develop a game on this list! == Cool :) But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project? == What has to be done to add a game on this list? == The right owners has to give an licence/authorization to BGA. Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract. Important: you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below). == Why all best-sellers games I love are not on that list? == As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA. So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this". We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-. == I want my prototype/unpublished game on BGA == You should take into account the fol == What if I really want to develop a particular game that is NOT on the list below? == This is the most asked question, to please follow the instructions: 0: In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it? Continue to 1. 1: At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher. To find the original publisher: _ check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish). _ check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time. _ very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher. Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome. Continue to 2 2: Read the publisher list below to check if BGA already work with this publisher. If YES, continue to 3. If NO, continue to 4. However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone. 3: Is there already a game licenced by this publisher that has to be developed? If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another. If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop. If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization! 4: We never worked with this publisher before. If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :) If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation. Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA. 93bf4d69ac7675fd10a26554fcdbc8beae355543 961 960 2013-09-30T19:39:27Z Sourisdudesert 1 /* Wow, I WANT to develop a game on this list! */ wikitext text/x-wiki == What is a "licence" == Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website. == Are all games on BGA licenced by their respective right owners? == Yes. == What if I start developing a game that is not on the "Available licences"? == We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process. Exception: games on the public domain are of course not concerned. == Wow, I WANT to develop a game on this list! == Cool :) But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project? [http://en.studio.boardgamearena.com/#!projects Check the list of current projects] == What has to be done to add a game on this list? == The right owners has to give an licence/authorization to BGA. Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract. Important: you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below). == Why all best-sellers games I love are not on that list? == As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA. So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this". We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-. == I want my prototype/unpublished game on BGA == You should take into account the fol == What if I really want to develop a particular game that is NOT on the list below? == This is the most asked question, to please follow the instructions: 0: In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it? Continue to 1. 1: At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher. To find the original publisher: _ check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish). _ check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time. _ very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher. Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome. Continue to 2 2: Read the publisher list below to check if BGA already work with this publisher. If YES, continue to 3. If NO, continue to 4. However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone. 3: Is there already a game licenced by this publisher that has to be developed? If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another. If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop. If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization! 4: We never worked with this publisher before. If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :) If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation. Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA. 7abedae86b4ee8ee613db9c3c10357521b22c3ae 962 961 2013-09-30T19:39:56Z Sourisdudesert 1 /* What has to be done to add a game on this list? */ wikitext text/x-wiki == What is a "licence" == Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website. == Are all games on BGA licenced by their respective right owners? == Yes. == What if I start developing a game that is not on the "Available licences"? == We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process. Exception: games on the public domain are of course not concerned. == Wow, I WANT to develop a game on this list! == Cool :) But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project? [http://en.studio.boardgamearena.com/#!projects Check the list of current projects] == What has to be done to add a game on this list? == The right owners has to give an licence/authorization to BGA. Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract. '''Important''': you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below). == Why all best-sellers games I love are not on that list? == As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA. So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this". We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-. == I want my prototype/unpublished game on BGA == You should take into account the fol == What if I really want to develop a particular game that is NOT on the list below? == This is the most asked question, to please follow the instructions: 0: In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it? Continue to 1. 1: At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher. To find the original publisher: _ check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish). _ check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time. _ very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher. Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome. Continue to 2 2: Read the publisher list below to check if BGA already work with this publisher. If YES, continue to 3. If NO, continue to 4. However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone. 3: Is there already a game licenced by this publisher that has to be developed? If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another. If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop. If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization! 4: We never worked with this publisher before. If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :) If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation. Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA. c783045c457de98285b6e6366084d147ad7cf7ee 963 962 2013-09-30T19:53:15Z Sourisdudesert 1 /* I want my prototype/unpublished game on BGA */ wikitext text/x-wiki == What is a "licence" == Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website. == Are all games on BGA licenced by their respective right owners? == Yes. == What if I start developing a game that is not on the "Available licences"? == We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process. Exception: games on the public domain are of course not concerned. == Wow, I WANT to develop a game on this list! == Cool :) But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project? [http://en.studio.boardgamearena.com/#!projects Check the list of current projects] == What has to be done to add a game on this list? == The right owners has to give an licence/authorization to BGA. Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract. '''Important''': you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below). == Why all best-sellers games I love are not on that list? == As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA. So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this". We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-. == I want my prototype/unpublished game on BGA == This is possible, BUT most of the time, we consider this is a bad idea for the following reasons: * if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it. * as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes don't have a big audience on BGA. * we also discourage you to develop your own game: we build better games adaptation with a designer that focus on the gameplay and a developer that focus on the realization. So basically you can develop your prototype/unpublished game on BGA, but we encourage you to do it only if you are in one/several of the situation below: * the game is going to be published in the near future. * the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...). * you want to test a game with a big number of players to finalize some minor things ("balance"). == What if I really want to develop a particular game that is NOT on the list below? == This is the most asked question, to please follow the instructions: 0: In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it? Continue to 1. 1: At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher. To find the original publisher: _ check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish). _ check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time. _ very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher. Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome. Continue to 2 2: Read the publisher list below to check if BGA already work with this publisher. If YES, continue to 3. If NO, continue to 4. However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone. 3: Is there already a game licenced by this publisher that has to be developed? If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another. If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop. If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization! 4: We never worked with this publisher before. If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :) If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation. Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA. 19303f4c227bf19a3b897b61ee7148f3592a5d7b 964 963 2013-09-30T19:54:07Z Sourisdudesert 1 /* What if I really want to develop a particular game that is NOT on the list below? */ wikitext text/x-wiki == What is a "licence" == Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website. == Are all games on BGA licenced by their respective right owners? == Yes. == What if I start developing a game that is not on the "Available licences"? == We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process. Exception: games on the public domain are of course not concerned. == Wow, I WANT to develop a game on this list! == Cool :) But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project? [http://en.studio.boardgamearena.com/#!projects Check the list of current projects] == What has to be done to add a game on this list? == The right owners has to give an licence/authorization to BGA. Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract. '''Important''': you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below). == Why all best-sellers games I love are not on that list? == As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA. So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this". We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-. == I want my prototype/unpublished game on BGA == This is possible, BUT most of the time, we consider this is a bad idea for the following reasons: * if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it. * as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes don't have a big audience on BGA. * we also discourage you to develop your own game: we build better games adaptation with a designer that focus on the gameplay and a developer that focus on the realization. So basically you can develop your prototype/unpublished game on BGA, but we encourage you to do it only if you are in one/several of the situation below: * the game is going to be published in the near future. * the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...). * you want to test a game with a big number of players to finalize some minor things ("balance"). == What if I really want to develop a particular game that is NOT on the list below? == This is the most asked question, to please follow the instructions: === 0: === In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it? Continue to 1. === 1: === At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher. To find the original publisher: _ check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish). _ check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time. _ very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher. Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome. Continue to 2 === 2: === Read the publisher list below to check if BGA already work with this publisher. If YES, continue to 3. If NO, continue to 4. However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone. === 3: === Is there already a game licenced by this publisher that has to be developed? If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another. If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop. If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization! === 4: === We never worked with this publisher before. If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :) If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation. Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA. c63fc6b89c725461f6a5a66b986dd8c92d176159 965 964 2013-09-30T19:55:45Z Sourisdudesert 1 /* 1: */ wikitext text/x-wiki == What is a "licence" == Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website. == Are all games on BGA licenced by their respective right owners? == Yes. == What if I start developing a game that is not on the "Available licences"? == We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process. Exception: games on the public domain are of course not concerned. == Wow, I WANT to develop a game on this list! == Cool :) But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project? [http://en.studio.boardgamearena.com/#!projects Check the list of current projects] == What has to be done to add a game on this list? == The right owners has to give an licence/authorization to BGA. Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract. '''Important''': you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below). == Why all best-sellers games I love are not on that list? == As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA. So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this". We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-. == I want my prototype/unpublished game on BGA == This is possible, BUT most of the time, we consider this is a bad idea for the following reasons: * if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it. * as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes don't have a big audience on BGA. * we also discourage you to develop your own game: we build better games adaptation with a designer that focus on the gameplay and a developer that focus on the realization. So basically you can develop your prototype/unpublished game on BGA, but we encourage you to do it only if you are in one/several of the situation below: * the game is going to be published in the near future. * the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...). * you want to test a game with a big number of players to finalize some minor things ("balance"). == What if I really want to develop a particular game that is NOT on the list below? == This is the most asked question, to please follow the instructions: === 0: === In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it? Continue to 1. === 1: === At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher. To find the original publisher: * check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish). * check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time. * very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher. Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome. Continue to 2 === 2: === Read the publisher list below to check if BGA already work with this publisher. If YES, continue to 3. If NO, continue to 4. However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone. === 3: === Is there already a game licenced by this publisher that has to be developed? If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another. If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop. If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization! === 4: === We never worked with this publisher before. If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :) If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation. Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA. b6c44a94b871bfa92a9307663bda5a41f4d0ed7b 966 965 2013-09-30T19:56:30Z Sourisdudesert 1 /* 2: */ wikitext text/x-wiki == What is a "licence" == Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website. == Are all games on BGA licenced by their respective right owners? == Yes. == What if I start developing a game that is not on the "Available licences"? == We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process. Exception: games on the public domain are of course not concerned. == Wow, I WANT to develop a game on this list! == Cool :) But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project? [http://en.studio.boardgamearena.com/#!projects Check the list of current projects] == What has to be done to add a game on this list? == The right owners has to give an licence/authorization to BGA. Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract. '''Important''': you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below). == Why all best-sellers games I love are not on that list? == As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA. So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this". We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-. == I want my prototype/unpublished game on BGA == This is possible, BUT most of the time, we consider this is a bad idea for the following reasons: * if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it. * as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes don't have a big audience on BGA. * we also discourage you to develop your own game: we build better games adaptation with a designer that focus on the gameplay and a developer that focus on the realization. So basically you can develop your prototype/unpublished game on BGA, but we encourage you to do it only if you are in one/several of the situation below: * the game is going to be published in the near future. * the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...). * you want to test a game with a big number of players to finalize some minor things ("balance"). == What if I really want to develop a particular game that is NOT on the list below? == This is the most asked question, to please follow the instructions: === 0: === In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it? Continue to 1. === 1: === At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher. To find the original publisher: * check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish). * check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time. * very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher. Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome. Continue to 2 === 2: === Read the publisher list from the "available licence" page to check if BGA already work with this publisher. If YES, continue to 3. If NO, continue to 4. However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone. === 3: === Is there already a game licenced by this publisher that has to be developed? If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another. If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop. If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization! === 4: === We never worked with this publisher before. If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :) If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation. Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA. 26c04bdf3793ee0fa5b163639693fe822930ff25 967 966 2013-09-30T19:57:56Z Sourisdudesert 1 wikitext text/x-wiki == What is a "licence" == Almost all games on Board Game Arena platform are adaptations of existing commercial "real" board games. To propose an adaption of one of this board game on a website, the right owners must grant a licence/authorization to this website. == Are all games on BGA licenced by their respective right owners? == Yes. == Where can I find available games licences == http://en.studio.boardgamearena.com/#!page/availablelicences == What if I start developing a game that is not on the "Available licences"? == We allow developers to start any project on the Studio. But when your project is going to be live on BGA, it will be rejected during the review process. Exception: games on the public domain are of course not concerned. == Wow, I WANT to develop a game on this list! == Cool :) But before creating a new project please takes some seconds to check if someone is not already developing this game. If this is the case, maybe you can propose to join the project? [http://en.studio.boardgamearena.com/#!projects Check the list of current projects] == What has to be done to add a game on this list? == The right owners has to give an licence/authorization to BGA. Publishers do not have to pay anything to BGA for this, they just have to give their "go". Most of the time, publishers wants to have a formal agreement and we signed a contract. '''Important''': you CAN'T take the initiative to ask a licence authorization on behalf of BGA, because the authorization has to be granted to BGA (read more below). == Why all best-sellers games I love are not on that list? == As you can imagine, the more popular a game is, the most difficult it is to have an agreement to host this game on BGA. So if you think about a particular very popular game that is not on this list, the reason for this rather be "we asked and this was impossible" than "we did'nt think of this". We are pretty lucky to have a very nice platform that convince the most prestigious publishers to host their games here, but of course we can't convince -everyone-. == I want my prototype/unpublished game on BGA == This is possible, BUT most of the time, we consider this is a bad idea for the following reasons: * if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it. * as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes don't have a big audience on BGA. * we also discourage you to develop your own game: we build better games adaptation with a designer that focus on the gameplay and a developer that focus on the realization. So basically you can develop your prototype/unpublished game on BGA, but we encourage you to do it only if you are in one/several of the situation below: * the game is going to be published in the near future. * the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...). * you want to test a game with a big number of players to finalize some minor things ("balance"). == What if I really want to develop a particular game that is NOT on the list below? == This is the most asked question, to please follow the instructions: === 0: === In any case: please, do not contact publishers without asking us before. Please imagine you are a game publisher who just published a popular game: what would you do if you received 40 emails from 40 developers speaking about "BGA platform" and wanting to build an adaptation on it? Continue to 1. === 1: === At first, you should determine who is the owner of the electronic rights of a game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because in general board games are translated&published in each countries by a local publisher. To find the original publisher: * check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably polish). * check the copyright notice at the end of the rules, where the original publisher is mentioned almost all the time. * very often, if two publishers are mentioned on a gamebox, the well-known publisher is the publisher from your country and the other one is the original publisher. Particular case: if the game is themed with a prestigious licence (Star Wars, Lord of the Ring, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licences owners are very restrictive, and there is 99% chance that an online adaptation on BGA is not welcome. Continue to 2 === 2: === Read the publisher list from the "available licence" page to check if BGA already work with this publisher. If YES, continue to 3. If NO, continue to 4. However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens sometimes that some publishers are not convinced by online boardgaming and this is their right to think this. BGA team regularly meet new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone. === 3: === Is there already a game licenced by this publisher that has to be developed? If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a licence for a game, a publisher expect that the game will be developed and published online. So we develop and publish a game before asking for another. If you really want to develop a game from this particular publisher, the best option for you is to help to develop the game that is currently licenced and then to ask us to request the game you'd like to develop. If NO: just ask us which game you want to develop and we would be happy to ask the publisher the authorization! === 4: === We never worked with this publisher before. If you have already developed a game on BGA, we would be happy to ask the publisher the authorization :) If this is your first game on BGA, we probably advise you to start with a game already on the list. Why? Because unfortunately, some developers are asking us to request a licence, and don't finish the development afterwards. When we ask for a licence, we are more comfortable if you already show that you are able to realize an adaptation. Particular case: if you already know the publisher PERSONALLY, or have some contact there, please tell us so we can help you to setup a contract to host a game adaptation on BGA. 04a8e9ded7e7fa61ef6e9a9a76858da7938e4856 970 967 2013-10-01T20:52:40Z Een 3 wikitext text/x-wiki == What's a "license" == Almost all games on the Board Game Arena platform are adaptations of existing commercial "real" board games. In order to host an adaptation of one of these board games on a website, the copyright owners must first grant a license/authorisation to this website. == Are all games on BGA licensed by their respective copyright owners? == Yes, for all games that are not in the public domain, BGA has been granted an authorisation to create and host an online version. == Where can I find a list of games for which a license has already been granted? == [http://en.studio.boardgamearena.com/#!page/availablelicences Check the list of available licenses] (NB: this page is restricted to developers registered in BGA studio. You'll need to enter your BGA studio credentials to access it) == What if I start developing a game that is not on the "Available licences" list? == We allow developers to start any project in the Studio. But when you submit your project to go live on BGA, it will be rejected during the review process if BGA doesn't hold a proper license for the game. Exception: games in the public domain are of course not concerned. == Wow, I WANT to develop a game on this list! == Great! :) But before creating a new project, please takes some seconds to check that someone is not already developing this game. If it is the case, maybe you can propose to join the project? [http://en.studio.boardgamearena.com/#!projects Check the list of current projects] == What needs to be done to add a game on this list? == The copyright owners have to give an license/authorisation to BGA. Publishers do not have to pay anything to BGA for this, they just need to give their "go". Most of the time, publishers want to have a formal agreement and we sign a contract with them. '''Important''': you CAN'T take the initiative to ask a license authorization on behalf of BGA, because the authorisation has to be granted to BGA (read more below). == Why aren't all the best-selling games that I love on that list? == As you can imagine, the more popular a game is, the most difficult it can be to get an agreement to host this game on BGA. So if you are thinking about a very popular game that is not on this list, the reason is most likely "we asked but it was not possible" and not "we didn't think of it". We are really happy to have been able to build a very nice platform that managed to convince some of the most prestigious publishers to host their games here, but of course we can't convince -everyone-. == I want to make my prototype/unpublished game available on BGA == This is possible, BUT most of the time, we consider this is a bad idea for the following reasons: * if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it. * as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes most likely won't get a big audience on BGA. * we also advise you against developing your own game: games adaptation are better when there is a designer whose focus is on the gameplay and a developer whose focus is on the implementation. So you definitely can develop your prototype/unpublished game on BGA, but we encourage you to think twice about it and do it only if you are in one/several of the situations below: * the game is going to be published in the near future * the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...) * you want to test your game with a big number of players to fine-tune some minor things ("balance" of the game). == What if I really want to develop a particular game that is NOT on the list below? == This is the most frequently asked question, so for a detailed answer please follow the white rabbit down these numbered instructions: === 0: === In any case: please, do not contact publishers without asking us before. Just put yourself in the shoes of a game publisher who just published a popular game: what would you think if you received 40 emails from 40 developers speaking about some "BGA platform" and wanting to build an adaptation on it? Proceed to 1. === 1: === First, you should determine who is the owner of the digital rights of the game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because very often board games are translated and published in different countries by a local publisher. To find the original publisher: * check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably Polish). * check the copyright notice at the end of the rules, where the original publisher is mentioned almost every time. * very often, if two publishers are mentioned on a gamebox, the well-known publisher is the local publisher from your country and the other one is the original publisher. Special case: if the game is themed with a prestigious licence (Star Wars, Lord of the Rings, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licenses owners are very restrictive, and there is 99% chance that an online adaptation on BGA would be impossible to manage. Continue to 2. === 2: === Read the list of publishers from the "available licenses" page to check if BGA is already working with this publisher. If YES, proceed to 3. If NO, jump to 4. However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens that some publishers are not convinced or interested by online boardgaming and it is their right to think so. The BGA team regularly meets new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone. === 3: === Is there already in the list a game licensed by this publisher that is available to be developed or under development? If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a license for a game, the publisher naturally expects that this game will be developed and published online. So we develop and publish a game before asking for another. If you really want to develop another game from this particular publisher, the best option for you is to help develop the game that is currently licensed and then ask us to request the game you'd like to develop. If NO: just ask us which game you want to develop and we will be happy to ask the publisher for his authorisation. === 4: === We have never worked with this publisher before. If you have already developed a game on BGA, we will be happy to contact the publisher to ask for an authorisation :) If this is your first game on BGA, we advise you to start with a game already on the list. Why? Because unfortunately, some developers ask us to request a license, and then don't finish the development. When we ask for a license, we are more comfortable if you have already shown your ability to realise an adaptation. Special case: if you know the publisher PERSONALLY, or have some contact there, please tell us so we can help you setup a contract allowing us to host a game adaptation on BGA. 7e176a08204233bebc4a4d93360a66c2b440a050 971 970 2013-10-01T20:54:58Z Een 3 wikitext text/x-wiki == What is a "license" exactly? == Almost all games on the Board Game Arena platform are adaptations of existing commercial "real" board games. In order to host an adaptation of one of these board games on a website, the copyright owners must first grant a license/authorisation to this website. == Are all games on BGA licensed by their respective copyright owners? == Yes, for all games that are not in the public domain, BGA has been granted an authorisation to create and host an online version. == Where can I find a list of games for which a license has already been granted? == [http://en.studio.boardgamearena.com/#!page/availablelicences Check the list of available licenses] (NB: this page is restricted to developers registered in BGA studio. You'll need to enter your BGA studio credentials to access it) == What if I start developing a game that is not on the "Available licences" list? == We allow developers to start any project in the Studio. But when you submit your project to go live on BGA, it will be rejected during the review process if BGA doesn't hold a proper license for the game. Exception: games in the public domain are of course not concerned. == Wow, I WANT to develop a game on this list! == Great! :) But before creating a new project, please takes some seconds to check that someone is not already developing this game. If it is the case, maybe you can propose to join the project? [http://en.studio.boardgamearena.com/#!projects Check the list of current projects] == What needs to be done to add a game on this list? == The copyright owners have to give an license/authorisation to BGA. Publishers do not have to pay anything to BGA for this, they just need to give their "go". Most of the time, publishers want to have a formal agreement and we sign a contract with them. '''Important''': you CAN'T take the initiative to ask a license authorization on behalf of BGA, because the authorisation has to be granted to BGA (read more below). == Why aren't all the best-selling games that I love on that list? == As you can imagine, the more popular a game is, the most difficult it can be to get an agreement to host this game on BGA. So if you are thinking about a very popular game that is not on this list, the reason is most likely "we asked but it was not possible" and not "we didn't think of it". We are really happy to have been able to build a very nice platform that managed to convince some of the most prestigious publishers to host their games here, but of course we can't convince -everyone-. == I want to make my prototype/unpublished game available on BGA == This is possible, BUT most of the time, we consider this is a bad idea for the following reasons: * if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it. * as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes most likely won't get a big audience on BGA. * we also advise you against developing your own game: games adaptation are better when there is a designer whose focus is on the gameplay and a developer whose focus is on the implementation. So you definitely can develop your prototype/unpublished game on BGA, but we encourage you to think twice about it and do it only if you are in one/several of the situations below: * the game is going to be published in the near future * the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...) * you want to test your game with a big number of players to fine-tune some minor things ("balance" of the game). == What if I really want to develop a particular game that is NOT on the list below? == This is the most frequently asked question, so for a detailed answer please follow the white rabbit down these numbered instructions: === 0: === In any case: please, do not contact publishers without asking us before. Just put yourself in the shoes of a game publisher who just published a popular game: what would you think if you received 40 emails from 40 developers speaking about some "BGA platform" and wanting to build an adaptation on it? Proceed to 1. === 1: === First, you should determine who is the owner of the digital rights of the game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because very often board games are translated and published in different countries by a local publisher. To find the original publisher: * check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably Polish). * check the copyright notice at the end of the rules, where the original publisher is mentioned almost every time. * very often, if two publishers are mentioned on a gamebox, the well-known publisher is the local publisher from your country and the other one is the original publisher. Special case: if the game is themed with a prestigious licence (Star Wars, Lord of the Rings, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licenses owners are very restrictive, and there is 99% chance that an online adaptation on BGA would be impossible to manage. Continue to 2. === 2: === Read the list of publishers from the "available licenses" page to check if BGA is already working with this publisher. If YES, proceed to 3. If NO, jump to 4. However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens that some publishers are not convinced or interested by online boardgaming and it is their right to think so. The BGA team regularly meets new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone. === 3: === Is there already in the list a game licensed by this publisher that is available to be developed or under development? If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a license for a game, the publisher naturally expects that this game will be developed and published online. So we develop and publish a game before asking for another. If you really want to develop another game from this particular publisher, the best option for you is to help develop the game that is currently licensed and then ask us to request the game you'd like to develop. If NO: just ask us which game you want to develop and we will be happy to ask the publisher for his authorisation. === 4: === We have never worked with this publisher before. If you have already developed a game on BGA, we will be happy to contact the publisher to ask for an authorisation :) If this is your first game on BGA, we advise you to start with a game already on the list. Why? Because unfortunately, some developers ask us to request a license, and then don't finish the development. When we ask for a license, we are more comfortable if you have already shown your ability to realise an adaptation. Special case: if you know the publisher PERSONALLY, or have some contact there, please tell us so we can help you setup a contract allowing us to host a game adaptation on BGA. f7fa9a78f5dd8ccffc5028a8d1ee6f5d98648d5b 972 971 2013-10-01T20:56:18Z Een 3 moved [[BGA Game licences]] to [[BGA Game licenses]]: typo wikitext text/x-wiki == What is a "license" exactly? == Almost all games on the Board Game Arena platform are adaptations of existing commercial "real" board games. In order to host an adaptation of one of these board games on a website, the copyright owners must first grant a license/authorisation to this website. == Are all games on BGA licensed by their respective copyright owners? == Yes, for all games that are not in the public domain, BGA has been granted an authorisation to create and host an online version. == Where can I find a list of games for which a license has already been granted? == [http://en.studio.boardgamearena.com/#!page/availablelicences Check the list of available licenses] (NB: this page is restricted to developers registered in BGA studio. You'll need to enter your BGA studio credentials to access it) == What if I start developing a game that is not on the "Available licences" list? == We allow developers to start any project in the Studio. But when you submit your project to go live on BGA, it will be rejected during the review process if BGA doesn't hold a proper license for the game. Exception: games in the public domain are of course not concerned. == Wow, I WANT to develop a game on this list! == Great! :) But before creating a new project, please takes some seconds to check that someone is not already developing this game. If it is the case, maybe you can propose to join the project? [http://en.studio.boardgamearena.com/#!projects Check the list of current projects] == What needs to be done to add a game on this list? == The copyright owners have to give an license/authorisation to BGA. Publishers do not have to pay anything to BGA for this, they just need to give their "go". Most of the time, publishers want to have a formal agreement and we sign a contract with them. '''Important''': you CAN'T take the initiative to ask a license authorization on behalf of BGA, because the authorisation has to be granted to BGA (read more below). == Why aren't all the best-selling games that I love on that list? == As you can imagine, the more popular a game is, the most difficult it can be to get an agreement to host this game on BGA. So if you are thinking about a very popular game that is not on this list, the reason is most likely "we asked but it was not possible" and not "we didn't think of it". We are really happy to have been able to build a very nice platform that managed to convince some of the most prestigious publishers to host their games here, but of course we can't convince -everyone-. == I want to make my prototype/unpublished game available on BGA == This is possible, BUT most of the time, we consider this is a bad idea for the following reasons: * if your game has not been published yet, there is certainly a good reason - most of the time there is still some more work to do on the game itself. Publishing a game on BGA that is not 100% finalized won't help you to finalize it. * as a rule of thumb, popular board games on BGA are games that are popular in the real world. As a consequence prototypes most likely won't get a big audience on BGA. * we also advise you against developing your own game: games adaptation are better when there is a designer whose focus is on the gameplay and a developer whose focus is on the implementation. So you definitely can develop your prototype/unpublished game on BGA, but we encourage you to think twice about it and do it only if you are in one/several of the situations below: * the game is going to be published in the near future * the game design process is really 100% done: the game is ready to be published in its current shape (ex: self-publishing game, game in a crowdfunding process...) * you want to test your game with a big number of players to fine-tune some minor things ("balance" of the game). == What if I really want to develop a particular game that is NOT on the list below? == This is the most frequently asked question, so for a detailed answer please follow the white rabbit down these numbered instructions: === 0: === In any case: please, do not contact publishers without asking us before. Just put yourself in the shoes of a game publisher who just published a popular game: what would you think if you received 40 emails from 40 developers speaking about some "BGA platform" and wanting to build an adaptation on it? Proceed to 1. === 1: === First, you should determine who is the owner of the digital rights of the game. Most of the time, this is the original publisher of the game. The original publisher is not always easy to find, because very often board games are translated and published in different countries by a local publisher. To find the original publisher: * check in which country the game has been published first (ex: If it's in Poland, the original publisher is probably Polish). * check the copyright notice at the end of the rules, where the original publisher is mentioned almost every time. * very often, if two publishers are mentioned on a gamebox, the well-known publisher is the local publisher from your country and the other one is the original publisher. Special case: if the game is themed with a prestigious licence (Star Wars, Lord of the Rings, some TV show, some well known novel...), you can stop here immediately: contracts between game publishers and prestigious licenses owners are very restrictive, and there is 99% chance that an online adaptation on BGA would be impossible to manage. Continue to 2. === 2: === Read the list of publishers from the "available licenses" page to check if BGA is already working with this publisher. If YES, proceed to 3. If NO, jump to 4. However, if the publisher is listed as "not working with BGA", you can stop here immediately. It happens that some publishers are not convinced or interested by online boardgaming and it is their right to think so. The BGA team regularly meets new publishers during board games events to show them the platform, so we're working on this but -again- we cannot convince everyone. === 3: === Is there already in the list a game licensed by this publisher that is available to be developed or under development? If YES: as a rule of thumb, we do not ask more than one game to a publisher at a time. When we ask a license for a game, the publisher naturally expects that this game will be developed and published online. So we develop and publish a game before asking for another. If you really want to develop another game from this particular publisher, the best option for you is to help develop the game that is currently licensed and then ask us to request the game you'd like to develop. If NO: just ask us which game you want to develop and we will be happy to ask the publisher for his authorisation. === 4: === We have never worked with this publisher before. If you have already developed a game on BGA, we will be happy to contact the publisher to ask for an authorisation :) If this is your first game on BGA, we advise you to start with a game already on the list. Why? Because unfortunately, some developers ask us to request a license, and then don't finish the development. When we ask for a license, we are more comfortable if you have already shown your ability to realise an adaptation. Special case: if you know the publisher PERSONALLY, or have some contact there, please tell us so we can help you setup a contract allowing us to host a game adaptation on BGA. f7fa9a78f5dd8ccffc5028a8d1ee6f5d98648d5b Faq 0 3 968 911 2013-10-01T19:06:03Z Een 3 /* What do I need to play? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Thinking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple account and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had a bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. 0cda94e7386cdf0bfd3e819363c68c75b4f78c9b Browser support 0 13 969 426 2013-10-01T19:11:36Z Een 3 wikitext text/x-wiki <h3>For the best experience, we recommend:</h3> * '''Google Chrome 10+''' [http://www.google.com/chrome Windows] [http://www.google.com/chrome?platform=mac Mac] [http://www.google.com/chrome?platform=linux Linux] * '''Mozilla Firefox 4+''' [http://www.mozilla.org/products/firefox/ Windows] [http://www.mozilla.org/products/firefox/ Mac] [http://www.mozilla.org/products/firefox/ Linux] Board Game Arena takes advantage of the most recent web technology to make it possible for you to play without installing anything on your computer: no software to download or update, no plugins to install, etc. Consequently, to play you need to use a modern web browser. Generally speaking, the more recent your web browser is, the more pleasant your game experience on Board Game Arena will be. This website makes intensive use of Javascript and your browser's graphics capabilities. Thus, if you want to have the best gaming experience with Board Game Arena, you should use one of the browsers listed above. However, we officially support the following browsers: * Google Chrome 4+ * Mozilla Firefox 3.5+ * Internet Explorer 9+ * Safari 4+ (Note: We do NOT support playing on iPads or similar tablets.) [[Category:Help]] 8a4654e948afc3ad04edef323b0769cd8cdcae40 BGA Game licences 0 132 973 2013-10-01T20:56:18Z Een 3 moved [[BGA Game licences]] to [[BGA Game licenses]]: typo wikitext text/x-wiki #REDIRECT [[BGA Game licenses]] a99c9debf146a8f72d9071adcdf88894fcd0b39a Gamehelpmachiavelli 0 133 974 2013-10-03T20:53:55Z Emanueles 3943 Created page with " == Game materials == Machiavelli is played with 2 or more french decks without using jokers. == Goal of the game == The game ends when a player plays all his cards or when t..." wikitext text/x-wiki == Game materials == Machiavelli is played with 2 or more french decks without using jokers. == Goal of the game == The game ends when a player plays all his cards or when the deck is depleted. == Game setup == Every player get 15 cards. Cards are secret and visible by its owner only. Put the rest of the deck on the table. == How to play == Each turn players can do a sequence of action, until the turn ends. Actions: * ''Draw a card'' The player can draw a card from the deck and his turn ends. * ''Play cards'' Player can play cards from his hand, laying them on the table and respecting the following rules: 1) Cards on the table must always form groups that contain at least 3 cards. 2) Groups on the table must be sets or runs. - Sets are groups of 3 or 4 cards of the same value (e.g. Q♥, Q♦, Q♣). - Runs are groups of cards of the same suit whose values are in sequence (e.g. 8♥,9♥,10♥,J♥,Q♥). The card rank start from ace to king: A, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K. Cards can be played also melding them to an existing group on the table as long as the previous rules are respected (e.g. player decides to meld 3♣, 7♣, 8♣ to an existing run on the table, made by 4♣, 5♣, 6♣ of clubs. He can meld the cards in the right sequence). * ''Take cards'' Player can take one or more groups of cards from the table adding them to his hand. Before his turn ends, he must play all cards he took from the table. Player may play these cards creating new groups, different from the previous ones, and using cards he already had in hand too. Example: Groups on the table: 3♣, 4♣, 5♣, 6♣ Q♥, Q♦, Q spades Player's hand: 5♣, 7♣, 8♣, Q♣, J♥, K♥ Player takes the 2 groups on the table, then he plays cards creating these new groups: 3♣, 4♣, 5♣ 5♣, 6♣, 7♣, 8♣ J♥, Q♥, K♥ Q♦, Q♠, Q♣ * ''Restore'' If a player took cards from the table and he is no more able to play all token cards, he may force his turn ends by restoring the original game situation on the table and of his hand. He must put back the token cards on the table, restoring the original groups and collecting cards he had in his hand that he may have played. Once restored, player must draw 3 cards from the deck as penalty. * ''Pass'' Player can pass only if he played cards and if he has no cards taken from the table in his hand. == End of the game == Game ends as soon as a player has no more cards in his hand or the deck is depleted. In the second case, the winner is the player with less cards in his hand. 88b66124042dac597c46d922ef5de478b913914c 975 974 2013-10-03T21:05:48Z Emanueles 3943 wikitext text/x-wiki == Game materials == Machiavelli is played with 2 or more french decks without using jokers. == Goal of the game == The game ends when a player plays all his cards or when the deck is depleted. == Game setup == Every player get 15 cards. Cards are secret and visible by its owner only. Put the rest of the deck on the table. == How to play == Each turn players can do a sequence of action, until the turn ends. Actions: * ''Draw a card'' The player can draw a card from the deck and his turn ends. * ''Play cards'' Player can play cards from his hand, laying them on the table and respecting the following rules: 1) Cards on the table must always form groups that contain at least 3 cards. 2) Groups on the table must be sets or runs. - Sets are groups of 3 or 4 cards of the same value (e.g. Q♥, Q♦, Q♣). - Runs are groups of cards of the same suit whose values are in sequence (e.g. 8♥,9♥,10♥,J♥,Q♥). The card rank start from ace to king: A, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K. Cards can be played also melding them to an existing group on the table as long as the previous rules are respected (e.g. player decides to meld 3♣, 7♣, 8♣ to an existing run on the table, made by 4♣, 5♣, 6♣ of clubs. He can meld the cards in the right sequence). * ''Take cards'' Player can take one or more groups of cards from the table adding them to his hand. Before his turn ends, he must play all cards he took from the table. Player may play these cards creating new groups, different from the previous ones, and using cards he already had in hand too. Example: Groups on the table: 3♣, 4♣, 5♣, 6♣ Q♥, Q♦, Q spades Player's hand: 5♣, 7♣, 8♣, Q♣, J♥, K♥ Player takes the 2 groups on the table, then he plays cards creating these new groups: 3♣, 4♣, 5♣ 5♣, 6♣, 7♣, 8♣ J♥, Q♥, K♥ Q♦, Q♠, Q♣ * ''Restore'' If a player took cards from the table and he is no more able to play all token cards, he may force his turn ends by restoring the original game situation on the table and of his hand. He must put back the token cards on the table, restoring the original groups and collecting cards he had in his hand that he may have played. Once restored, player must draw 3 cards from the deck as penalty. In the BGA version the ''Restore'' action can be automatically performed clicking on a specific button. Cards token from the table are tagged with a red sign as reminder to play it before passing. * ''Pass'' Player can pass only if he played cards and if he has no cards taken from the table in his hand. == End of the game == Game ends as soon as a player has no more cards in his hand or the deck is depleted. In the second case, the winner is the player with less cards in his hand. 084c9a0a090271d58fb69df9c8e4e1e09774add0 987 975 2013-10-21T12:01:19Z Nalafab 2897 /* How to play */ wikitext text/x-wiki == Game materials == Machiavelli is played with 2 or more french decks without using jokers. == Goal of the game == The game ends when a player plays all his cards or when the deck is depleted. == Game setup == Every player get 15 cards. Cards are secret and visible by its owner only. Put the rest of the deck on the table. == How to play == Each turn players can do a sequence of action, until the turn ends. Actions: * ''Draw a card'' The player can draw a card from the deck and his turn ends. * ''Play cards'' Player can play cards from his hand, laying them on the table and respecting the following rules: 1) Cards on the table must always form groups that contain at least 3 cards. 2) Groups on the table must be sets or runs. - Sets are groups of 3 or 4 cards of the same value (e.g. Q♥, Q♦, Q♣). - Runs are groups of cards of the same suit whose values are in sequence (e.g. 8♥,9♥,10♥,J♥,Q♥). The card rank start from ace to king: A, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K. Cards can be played also melding them to an existing group on the table as long as the previous rules are respected (e.g. player decides to meld 3♣, 7♣, 8♣ to an existing run on the table, made by 4♣, 5♣, 6♣ of clubs. He can meld the cards in the right sequence). * ''Take cards'' Player can take one or more groups of cards from the table adding them to his hand. Before his turn ends, he must play all cards he took from the table. Player may play these cards creating new groups, different from the previous ones, and using cards he already had in hand too. Example: Groups on the table: 3♣, 4♣, 5♣, 6♣ / Q♥, Q♦, Q♠ Player's hand: 5♣, 7♣, 8♣, Q♣, J♥, K♥ Player takes the 2 groups on the table, then he plays cards creating these new groups: 3♣, 4♣, 5♣ / 5♣, 6♣, 7♣, 8♣ / J♥, Q♥, K♥ / Q♦, Q♠, Q♣ * ''Restore'' If a player took cards from the table and he is no more able to play all token cards, he may force his turn ends by restoring the original game situation on the table and of his hand. He must put back the token cards on the table, restoring the original groups and collecting cards he had in his hand that he may have played. Once restored, player must draw 3 cards from the deck as penalty. In the BGA version the ''Restore'' action can be automatically performed clicking on a specific button. Cards token from the table are tagged with a red sign as reminder to play it before passing. * ''Pass'' Player can pass only if he played cards and if he has no cards taken from the table in his hand. == End of the game == Game ends as soon as a player has no more cards in his hand or the deck is depleted. In the second case, the winner is the player with less cards in his hand. d8faf700b45b7213c3d62812cebb4f362019a186 991 987 2013-11-12T21:51:15Z Emanueles 3943 /* How to play */ wikitext text/x-wiki == Game materials == Machiavelli is played with 2 or more french decks without using jokers. == Goal of the game == The game ends when a player plays all his cards or when the deck is depleted. == Game setup == Every player get 15 cards. Cards are secret and visible by its owner only. Put the rest of the deck on the table. == How to play == Each turn players can do a sequence of action, until the turn ends. Actions: * ''Draw a card'' The player can draw a card from the deck and his turn ends. * ''Play cards'' Player can play cards from his hand, laying them on the table and respecting the following rules: 1) Cards on the table must always form groups that contain at least 3 cards. 2) Groups on the table must be sets or runs. - Sets are groups of 3 or 4 cards of the same value (e.g. Q♥, Q♦, Q♣). - Runs are groups of cards of the same suit whose values are in sequence (e.g. 8♥,9♥,10♥,J♥,Q♥). The card rank start from ace to king: A, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K. Cards can be played also melding them to an existing group on the table as long as the previous rules are respected (e.g. player decides to meld 3♣, 7♣, 8♣ to an existing run on the table, made by 4♣, 5♣, 6♣ of clubs. He can meld the cards in the right sequence). * ''Take cards'' Player can take one or more groups of cards from the table adding them to his hand. Before his turn ends, he must play all cards he took from the table. Player may play these cards creating new groups, different from the previous ones, and using cards he already had in hand too. Example: Groups on the table: 3♣, 4♣, 5♣, 6♣ / Q♥, Q♦, Q♠ Player's hand: 5♣, 7♣, 8♣, Q♣, J♥, K♥ Player takes the 2 groups on the table, then he plays cards creating these new groups: 3♣, 4♣, 5♣ / 5♣, 6♣, 7♣, 8♣ / J♥, Q♥, K♥ / Q♦, Q♠, Q♣ * ''Restore'' If a player took cards from the table and he is no more able to play all token cards, he may force his turn ends by restoring the original game situation on the table and of his hand. He must put back the token cards on the table, restoring the original groups and collecting cards he had in his hand that he may have played. Once restored, player must draw 1 cards from the deck and pass. In case player is not able to restore, the other players will help him to do it and then he must draw 3 cards as penalty. NOTE WELL: In the BGA version cards token from the table are tagged with a red sign as reminder to play it before passing. '''The ''Restore'' action can be automatically performed clicking on a specific button and player receive 1 card from the deck'''. 3 cards penalty is not considered. * ''Pass'' Player can pass only if he played cards and if he has no cards taken from the table in his hand. == End of the game == Game ends as soon as a player has no more cards in his hand or the deck is depleted. In the second case, the winner is the player with less cards in his hand. ff889e5ec7853a9c7602e22ae96a6b0981540983 Gamehelptokaido 0 134 977 2013-10-11T13:39:13Z Nikos messis 4024 Created page with "- if you enter a panorama space,either pick that panorama or pick a cherry tree worth 2 points and 1 coin - if you enter a hot spring space,either pick the hot spring or pay 1..." wikitext text/x-wiki - if you enter a panorama space,either pick that panorama or pick a cherry tree worth 2 points and 1 coin - if you enter a hot spring space,either pick the hot spring or pay 1 coin to pick a bath house tile worth 4 points - if you enter a souvenir shop,either buy souvenir as usual or get 1 legendary item instead,there are 6 items of 3 kinds,type 1 is worth 1 point for every souvenir and cost 1 coin,type 2 cost 2 coin and count as a family of his own (so if you have a full set already it's worth 9 point) and type 3 give cost 3 coins and give you 8 points straight - if you enter a farm you can go instead to a gambling house,bet 2 coins and throw a dice... the dice is either 0x 1x 2x 3x or 4x so you either lose 2 coins,gain 0 coins,gain 2 coin,gain 4 coin or gain 6 coins - if you enter a temple you can pay 1 coin for an amulet of your choice,amulet effect include 1) if you get the lead,get another turn 2) get a free meal 3) get both choice when you enter a space 4) throw the gamble dice and get coin equal to the value 5) get to a space occupied by another player 6) coin spent on an item go to the temple instead (you still get the item) - if you enter an encounter space you can get a caligraphy item instead which scores point at the end of the game depending on how you play, these include 1) score 3 point for every skipped meal 2) score 2 point for every coin unspent you have in the end 3) score 3 point for every completed panorama and 1 point for every cherry tree 4) score 2 point per legendary item and 1 point for every souvenir 5) score 6 point if you are the last to arrive at the final inn,4 point if you are the second to last player and 2 point in the other case's 6) score 2 point per accomplishment and 1 point for every caligraphy item to complete it all there are 6 new travelers 1) the yakuza - 5 coins - everytime he arrives on one of the three inn he can bet a single coin to the gambling house 2) the gourmet - 2 coins - he scores point equal to the price of the meal he eats 3) the old lady - 4 coins - when she stops on an encounter space, she can get both the encounter AND the caligraphy item 4) the superstitious woman - 4 coins - when she stops on a temple space,she can both donate coin to the temple AND buy an amulet 5) the kid - 3 coins - when he arrives on one of the three inn he gets a free souvenir 6) the souvenir seller - 0 coins - when he stops at a panorama he gets one cointeasel Written by teasel 8ca5663754ea3bc364dde6dadccb5f7c673cc64f 981 977 2013-10-17T06:46:37Z Hofty 3828 wikitext text/x-wiki * if you enter a panorama space,either pick that panorama or pick a cherry tree worth 2 points and 1 coin * if you enter a hot spring space,either pick the hot spring or pay 1 coin to pick a bath house tile worth 4 points * if you enter a souvenir shop,either buy souvenir as usual or get 1 legendary item instead,there are 6 items of 3 kinds,type 1 is worth 1 point for every souvenir and cost 1 coin,type 2 cost 2 coin and count as a family of his own (so if you have a full set already it's worth 9 point) and type 3 give cost 3 coins and give you 8 points straight * if you enter a farm you can go instead to a gambling house,bet 2 coins and throw a dice... the dice is either 0x 1x 2x 3x or 4x so you either lose 2 coins,gain 0 coins,gain 2 coin,gain 4 coin or gain 6 coins * if you enter a temple you can pay 1 coin for an amulet of your choice,amulet effect include *# if you get the lead,get another turn *# get a free meal *# get both choice when you enter a space *# throw the gamble dice and get coin equal to the value *# get to a space occupied by another player *# coin spent on an item go to the temple instead (you still get the item) * if you enter an encounter space you can get a caligraphy item instead which scores point at the end of the game depending on how you play, these include *# score 3 point for every skipped meal *# score 2 point for every coin unspent you have in the end *# score 3 point for every completed panorama and 1 point for every cherry tree *# score 2 point per legendary item and 1 point for every souvenir *# score 6 point if you are the last to arrive at the final inn,4 point if you are the second to last player and 2 point in the other case's *# score 2 point per accomplishment and 1 point for every caligraphy item * to complete it all there are 6 new travelers *# the yakuza - 5 coins - everytime he arrives on one of the three inn he can bet a single coin to the gambling house *# the gourmet - 2 coins - he scores point equal to the price of the meal he eats *# the old lady - 4 coins - when she stops on an encounter space, she can get both the encounter AND the caligraphy item *# the superstitious woman - 4 coins - when she stops on a temple space,she can both donate coin to the temple AND buy an amulet *# the kid - 3 coins - when he arrives on one of the three inn he gets a free souvenir *# the souvenir seller - 0 coins - when he stops at a panorama he gets one coin a46e8ef670d710022e52d42cb42129d1c576b1b8 984 981 2013-10-18T17:43:11Z Hofty 3828 wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible. To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== '''Farm''' : The player earns 3 coins. '''Hot Spring''' : The player takes a Hot Spring card. These cards are worth 2 or 3 points. '''Temple''' : The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. '''Encounters''' : The player draws one Encounter card and receives a bonus: : * Shokunin - one Souvenir : * Annaibito - one Panorama : * Samurai - 3 points : * Kuge - 3 coins : * Miko - 1 point and 1 coin to the Temple (from the bank) '''Village''' : The player draws 3 Souvenir cards and can purchase one or more of these cards. : Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks. : Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection. : As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type. : * The first Souvenir in a set is worth 1 point. : * The second Souvenir in a set is worth 3 points. : * The third Souvenir in a set is worth 5 points. : * The fourth Souvenir in a set is worth 7 points. '''Panorama''' : Panoramas are made of 3, 4 or 5 sections. : When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ». : Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card. : '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy). '''Inns''' : All Travelers must stop at each Inn. : The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points. : The first traveler occupies the space nearest the road, and later travelers form a line after him. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. : He can then purchase one Meal card of his choice by paying its price. : He adds this card, face up, to his collection and places the remaining cards next to the board, face down. : He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards. : '''IMPORTANT:''' : * A traveler cannot taste the same culinary specialty twice during his journey. : * A traveler can never purchase more than one Meal card per Inn. : * A traveler is never obliged to purchase a Meal card. == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the achievement cards (Gourmet, Collector, Bather, Chatterbox) to the appropriate travelers. ---- '''(Extracted from the english rule book)''' f3bab9bef4594b16c6a61ddb881d33b21c87d290 997 984 2013-12-04T03:54:49Z Ched 4183 /* Fix up bulleted lists. */ wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible. To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== '''Farm''' : The player earns 3 coins. '''Hot Spring''' : The player takes a Hot Spring card. These cards are worth 2 or 3 points. '''Temple''' : The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. '''Encounters''' : The player draws one Encounter card and receives a bonus: :* Shokunin - one Souvenir :* Annaibito - one Panorama :* Samurai - 3 points :* Kuge - 3 coins :* Miko - 1 point and 1 coin to the Temple (from the bank) '''Village''' : The player draws 3 Souvenir cards and can purchase one or more of these cards. : Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks. : Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection. : As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type. :* The first Souvenir in a set is worth 1 point. :* The second Souvenir in a set is worth 3 points. :* The third Souvenir in a set is worth 5 points. :* The fourth Souvenir in a set is worth 7 points. '''Panorama''' : Panoramas are made of 3, 4 or 5 sections. : When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ». : Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card. : '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy). '''Inns''' : All Travelers must stop at each Inn. : The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points. : The first traveler occupies the space nearest the road, and later travelers form a line after him. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. : He can then purchase one Meal card of his choice by paying its price. : He adds this card, face up, to his collection and places the remaining cards next to the board, face down. : He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards. : '''IMPORTANT:''' :* A traveler cannot taste the same culinary specialty twice during his journey. :* A traveler can never purchase more than one Meal card per Inn. :* A traveler is never obliged to purchase a Meal card. == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the achievement cards (Gourmet, Collector, Bather, Chatterbox) to the appropriate travelers. ---- '''(Extracted from the english rule book)''' 9182c3f8aafc47e083dba6b17ff2727a22afddc5 998 997 2013-12-04T04:11:48Z Ched 4183 /* Added more information about the achievement cards. */ wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible. To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== '''Farm''' : The player earns 3 coins. '''Hot Spring''' : The player takes a Hot Spring card. These cards are worth 2 or 3 points. '''Temple''' : The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. '''Encounters''' : The player draws one Encounter card and receives a bonus: :* Shokunin - one Souvenir :* Annaibito - one Panorama :* Samurai - 3 points :* Kuge - 3 coins :* Miko - 1 point and 1 coin to the Temple (from the bank) '''Village''' : The player draws 3 Souvenir cards and can purchase one or more of these cards. : Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks. : Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection. : As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type. :* The first Souvenir in a set is worth 1 point. :* The second Souvenir in a set is worth 3 points. :* The third Souvenir in a set is worth 5 points. :* The fourth Souvenir in a set is worth 7 points. '''Panorama''' : Panoramas are made of 3, 4 or 5 sections. : When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ». : Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card. : '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy). '''Inns''' : All Travelers must stop at each Inn. : The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points. : The first traveler occupies the space nearest the road, and later travelers form a line after him. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. : He can then purchase one Meal card of his choice by paying its price. : He adds this card, face up, to his collection and places the remaining cards next to the board, face down. : He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards. : '''IMPORTANT:''' :* A traveler cannot taste the same culinary specialty twice during his journey. :* A traveler can never purchase more than one Meal card per Inn. :* A traveler is never obliged to purchase a Meal card. == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' e646fd159fcc1f219ba3be4e8385441df42ddaf9 Gamehelptzolkin 0 129 978 923 2013-10-15T22:12:51Z Firstbass 4055 /* Food Day */ wikitext text/x-wiki == '''For Each Round''' == - Each player takes their turn, going around the table - On a food day, feed your workers and take your rewards - Advance the Calendar == '''Player turn''' == - '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple) - '''Either place workers OR pick up workers''' -- ''Placing workers'': pay for the number of workers you place plus the cost noted next to each placed workers -- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either --- Use the action where your worker was standing --- Use a lower action on the wheel from where your worker was standing(if not standing on a free action space,pay 1 corn for each step back) --- Do nothing. == '''Food Day''' == -'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for. -- For each worker not fed, you lose 3 points -'''Take Rewards''' --''Middle of Age (Brown days)'' --- Receive items shown on the left edge of temples from step you are on and all steps below -- ''End of Age (Teal Days)'' --- Remove all Age 1 buildings and fill spaces with Age 2 buildings/ --- Receive points shown on the right edge of temples for the step you are on. --- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus. == '''Advance the Calendar''' == If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day. Otherwise: - The worker on the Starting Player space returns to the player -- If this person was not the starting player, they take the starting player marker. -- If they were the starting player, the starting player marker is moved to the player on his left - Advance the Tzolk'in Gear one day. - The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears. -- If you use this option, flip your board to dark side up. -- This does not avoid food days. 23abb93a403f6d112973adff7fc438db52a7ac31 About us 0 6 979 158 2013-10-16T05:57:12Z Wenleinotohou 4058 wikitext text/x-wiki First, we should say that we are gamers. Real, complete boardgames addicts. We designed '''Board Game Arena''' for players who can't play for real because of time, geographic or social constraints. We would like to provide a new game experience with the best of two worlds: video games and board games. Although we aim to provide high quality online games, we are still convinced that the best way to enjoy board games is around a *real* table with friends. This is one of the reason we strongly recommend you to buy physical copies of the games you discover on BGA. The other reason is simple to understand: each game sale is also a revenue for an author and an editor (... we've come full circle). [[Contact us]] 首先,我们认为自己是玩家。在现实生活中是从头彻尾的桌游爱好者。 由于时间,地域或者社区环境的原因有一些玩家不能在现实中游戏,这成为我们设计BGA的原因。我们希望借电脑游戏和桌面游戏这两者的精华,给玩家提供崭新的体验。 即使我们的目标是提供高质量的在线游戏,我们仍然相信享受桌游最好的方式是和朋友围在一张现实的桌子旁。这也是为什么我们建议您购买BGA上的桌游的实体版本。另一个原因很好理解,每份卖出的游戏可以给作者和编辑者带来收入。(...结果让我们回到了一开始的游戏方式) d7b0f542a6b2f75173e2553721b533b3750e192a Studio back-office 0 56 980 391 2013-10-16T08:54:43Z Sourisdudesert 1 wikitext text/x-wiki '''IMPORTANT''': the Studio back-office is now '''DEPRECATED'''. Most of its functionalities are now accessible from "Control Panel / Manage Games / Your games". You will find the URL to the Studio back-office in the 'resources.html' file at the root of your SFTP access. Here is a list and description of the links and functions in this back-office. Click on a menu to display its content. === Documentation === Contains links to this wiki, the development forum and the bugs forum. === Database === Contains a link to the Studio database administration tool (PHPMyAdmin). Your login / password for this tool is the same as for your SFTP access. ('''DEPRECATED''': now you can access to your game database with the link "Game Database" at the bottom of your game page). === Sources === Contains a form for committing your sources to the BGA repository. * Game name field should contain the name of your game (lower case, no space). Ex: puertorico * Comment field should contain your commit comment describing changes to the code since your last commit. You should commit from time to time when you hit some landmarks in your development. This is an extra assurance not to lose your code, and to have the possibility (by asking BGA administrators) to get a previous version of your code if you need to backtrack. ('''DEPRECATED''': now this function is available from your Control Panel). === Logs === Gives you a web based access to the studio server logs. ; Current table error log : main log of interest to you while developing, it contains the error happening at the table you are currently playing at. ('''DEPRECATED''': now you can access this log with the coreesponding link at the bottom of your game page). ; Current table request logs : this log traces all the actions happening at the table you are currently playing at. ('''DEPRECATED''': now you can access this log with the coreesponding link at the bottom of your game page). ; Javascript error log : this log traces all the Javascript errors happening on the client side. Errors are also briefly displayed in your browser, but in this log it's better formatted and you can look a it quietly. ('''DEPRECATED''': you should use your Javascript console / Firebug plugin to do this). ; Gameserver error log : this log traces all errors happening on the gameserver. It should mainly be useful if your game setup crashes (ie before your table is ready, so before errors are collected in the current table error log), for example if there is a syntax error in your 'dbmodel.sql' file. ('''DEPRECATED''': errors during the game setup appears now directly in a red error message during your "Express start"). ; HTTP error log : this log traces the web server errors. This is useful to look at PHP syntax errors and warnings. ('''DEPRECATED''': errors now appear directly in a red message during the game). Please note that the three last logs are common to all games being developed on the platform, so there may be some noise in the data you are interested in. You can open the log links in a different tab and just hit F5 when you need to refresh. The URL you will get for the new tab has a "?n=100" parameter that gives the number of lines to display: you can modify it in the URL if you need more. ffcb9ffc3be270bfd19b8f277d8d4d1c4029e27c Gamehelptimemasters 0 135 982 2013-10-17T17:40:54Z Sigmund3 4072 Time Masters Rules wikitext text/x-wiki Phases of the game: 1)Timer phase If at the beginning of the turn you have a full timer, you must choose to either: - activate it: in which case the timer and all the cards used to delay it are discarded. The spells on it remain in the Timer area and you must play them until the end of turn. - delay it: in which case you must put a card from your hand, with the card back showing, on that timer. If you have a card on a timer you will replenish your hand until you have one card less, such as 4 cards instead of 5. Two cards to delay the timer mean 3 card in your hand maximum and so on. If at the start of your turn you have a timer that is full, even if you pass the turn to replenish all your Ke, you must put a card from your hand to delay it. 2)Main phase: You may play Spells, Focus or Timers and also Spells that are on active timers. 3)Access spheres Phase You may take cards from the Spheres of Consciousness depending on the number of spells played during the turn. These new cards go directly in your hand. You can't choose to draw from the same sphere during the same turn. One spell and you can draw from the first level, two and you can draw from the second and so on. Starting with the third spell you can combine and choose, a first and second level spell. It is possible to take the second card from a level, which is not revealed. For this you must pay an extra cost. For example, to take the second card from the second level, you must play three spells. 4)Closing Phase Discard all your played spells and replenish your hand until you have 5 cards, or less if you have chosen to delay timers. End of game The game finishes when 2 of the 5 spheres are empty, or more exactly at the end of turn of the player who draws the card that makes it happen. The players score points such that a card of gives an amount of points equal to the level it belongs. In case of equality the player with the highest amount of Ke wins. f94cac307666332fc62671acdcba9b87c505bc77 983 982 2013-10-18T05:00:56Z Jamie ca 4076 wikitext text/x-wiki Phases of the game: 1)Timer phase If at the beginning of the turn you have a full timer, you must choose to either: - activate it: in which case the timer and all the cards used to delay it are discarded. The spells on it remain in the Timer area and you must play them until the end of turn. - delay it: in which case you must put a card from your hand, with the card back showing, on that timer. If you have a card on a timer you will replenish your hand until you have one card less, such as 4 cards instead of 5. Two cards to delay the timer mean 3 card in your hand maximum and so on. If at the start of your turn you have a timer that is full, even if you pass the turn to replenish all your Ke, you must put a card from your hand to delay it. 2)Main phase: You may play Spells, Focus or Timers and also Spells that are on active timers. 3)Access spheres Phase You may take cards from the Spheres of Consciousness depending on the number of spells played during the turn. These new cards go directly in your hand. You can't choose to draw from the same sphere during the same turn. One spell and you can draw from the first level, two and you can draw from the second and so on. Starting with the third spell you can combine and choose, a first and second level spell. It is possible to take the second card from a level, which is not revealed. For this you must pay an extra cost. For example, to take the second card from the second level, you must play three spells. 4)Closing Phase Discard all your played spells and replenish your hand until you have 5 cards, or less if you have chosen to delay timers. End of game The game finishes when 2 of the 5 spheres are empty, or more exactly at the end of turn of the player who draws the card that makes it happen. The players score points such that a card of gives an amount of points equal to the level it belongs. In case of equality the player with the highest amount of Ke wins. c5849fb07b0191de069bfcac949cda5e27d07595 Gamehelpchinagold 0 136 985 2013-10-19T12:15:21Z Elisha 2997 Created page with "Hi!" wikitext text/x-wiki Hi! c0a0ad26a634840c67a210fefdda76577b03a111 Game interface logic: yourgamename.js 0 88 988 902 2013-10-27T20:30:47Z Vaanatomic 2276 /* Players input */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ).play(); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Reversi example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 4cf3443c514462554d9e6824a05bc2c286383728 Gamehelphawaii 0 34 989 425 2013-11-05T16:44:26Z Uss wampanoag 4200 /* Game-End VP's: */ obvious error, kahunas instead of tikis wikitext text/x-wiki Overview: You are the chieftain of a kingdom (your placemat) with up to five villages (rows). You buy or go to the islands to get place tiles that you put in your villages. There are five rounds and you get a decreasing amount of resources each round with which to acquire place tiles. Its a many-paths-to-victory kind of game. (It has been described as Stone Age without the dice). There are three kinds of resources: 1) Feet - let you move around the board, or travel to the islands or go to the cove to catch fish. 2) Clam shells - let you buy place tiles from the board 3) Fruit - can be used in place of feet or clam shells in all-or-nothing fashion. If you substitute for feet, you must substitute the entire moving cost. If you substitute for clams, you must substitute the entire purchase price. Moving: Your chieftains start at the beach and it costs nothing to return there from the board. Each movement in from the beach costs one foot. Moving up, down, right, left or diagonal on the board costs one foot per space. Staying on a space costs one foot. To go to the islands, you use your boats and feet. The closest island costs three feet and the farthest costs six. You have to have the feet as well as the space on the boats for the feet. You get an immediate victory point bonus for going to the islands but you do not get a price token (more about that later). Also, you get the level 2 version of whatever place tile or item you are getting on the islands. For instance, to go to the six foot island, you would need either: A) two three-feet boats and six feet resources or B) you would need the four-foot boat (which comes with a prepaid foot) and the two-foot boat as well as five feet resources. That is the advantage of the pre-paid foot on the four-foot boat. == Purchasing: == To buy some thing from the board: Select the price token (round colored circle with number inside) on the space with the place tile or item you want. If there is more than one place tile available on that space, you will be given a choice of which one you want. The movement cost will be in feet and the purchase price will be in clam shells but you can substitute either or both with fruit if you have it. You gain the price token for the round. There must be an available price token in order to purchase something from that space. You can pay double to get the level 2 version, which for most tiles is double effect. You place it in the village (row) of your choice. You must be able to place it in order to purchase it. A) You can only have one of each type of place tile in each village. For instance, you cannot have a foot (1) hut and a foot (2) hut in the same village but you can have a coconut fruit (1) tree and a breadfruit (2) tree in the same village. B) You can have only one god in each village. You can only have one of each type of god in your whole kingdom and the god vp effects are kingdom-wide. B) Each village must begin with a hut. The huts have a picture of a hut on them: foot hut, clam hut, spear hut, exchange hut, and long hut. ''' == Resources == ''' == Base reources == Base resources are on the round indicator. They decrease with each succeeding round. Everyone gets the base resources at the beginning of the round. Any unused resources can be used in the next round. == In-play resource bonuses == *The third, fourth and fifth villages give you 1, 2 and 3 clams respectively when you purchase Kahunas (Hawaiian priests) for them. *When you purchase for your kingdom the second, third and fourth Tikis, you are granted 1, 2, and 3 feet, respectively. *One or two of the island treasures are four fruit resources. == Resource Generators: == generate resources at the beginning of the next round. *Fruit level ones - one fruit *Fruit level twos - two fruit *Clam hut level one - one clam *Clam hut level two - two clams *Foot hut level one - one foot *Foot hut level two - two feet *Irrigation level two - one resource of your choice *Ku god - level one and two - one foot *Kane god level one - one clam *Kane god level two - two clams == Converter huts == Whenever you spend resources, a level 1 converter hut allows you to substitute one resource of your choice. So, for instance, you could move one space and buy something that has four price token on it with four fruit for the token and one clamshell being substituted for the one foot movement. Another example, you could go to the first island for two feet and one clamshell using a level 1 boat. The converter level 2 hut is the same but with any two resources. '''== Victory Points ==''' == In-play VP's: == *Going to the islands gives you a vp bonus. *Some of the treasures on the islands are 5 vp's. *Spear huts and the Ku god give you a bonus whenever you take a price token with crossed spears. Level 1 is 1 pt. bonus, Level 2 is two pt. bonus. == Round-End VP's: == There is a large sheild on the round indicator at the bottom. If the sum of price tokens and fish are greater than the number on the sheild, then you get a bonus. There is a large bonus for the player with highest sum score, a moderate bonus for the second highest and a token bonus for everyone else whose sum was greater than the sheild. Surfer place tiles lower the sheild value for qualifying for the bonus but surfers do not contribute to your sum when comparing to other players. Lono god level 1 gives you 2 vp's if you qualify for the bonus, and Lono god level 2 gives you 4 vp's if you qualify for the bonus == Game-End VP's: == A) Each village whose size does not extend to the Tikis (rightmost place tile of a row must intersect with the leftmost column of a Tiki) is ignored for end-game scoring - its place tiles do not count and neither does its Kahuna. The villages below it are not affected - each village must reach the leftmost Tiki independently. B) The Kahunas on the first, second, third, fourth and fifth villages scores the player five, five, ten, ten and fifteen points respectively. B) A hula dancer in a village scores one point for each place tile in her village including herself. A level 2 hula dancer scores two points instead of one for each place tile in her village including herself. C) Irrigation gives you pts for each type of fruit you have in that particular village: Breadfruit, guava, coconuts and bananas. D) The Long Hut level 2 is worth five points. The long hut level one just takes up space making it easier to reach the Kahunas but does not, itself, score points. E) The Laka god in your kingdom scores one pt for each fruit symbol on your place tiles in all of the villages which is the whole kingdom. Laka god level 2 scores two points for each fruit symbol. F) Kanaloa god scores two pts for each boat and each surfer on all the villages in the kingdom. Kanaloa 2 scores 4 pts for each boat and surfer. dd6fa6c5e9dd532aa9d7d11b65d0b8fbcfcc2eeb Gamehelpjumpgate 0 137 990 2013-11-09T07:08:53Z Chazm 3718 Initilal reference card info wikitext text/x-wiki Jump Gate == Turn Reference == Take two actions on your turn. You may take the same action twice. Fly ... to a neighboring planet. Jump ... to another more distant planet. Scan ... your current planet if it has any face-down resources. Land & Claim ... your current planet if it has no face-down resources and is unclaimed. Harvest ... 1 reource you marked with a Scan, or 1 unmarked resource at a planet with all face-up resources. Research ... refill your hand up to 5 cards. You may discard any number of cards before refilling. == Scoring Referece == If there are 7 or more markers on the Black Hole, the player(s) with the most markers on the Black Hole must discard their hidden resource cards before scoring. Otherwise, players reveal their hidden resource cards and add them to their collected resources for scoring. Score all collected resources as explained on the resource cards. Add 4 points for each planet claimed. Player with the highest score wins. c12f202940a60092b5a498dff6f39da8eaf83ca7 Gamehelparmadora 0 138 992 2013-11-12T22:15:04Z Luckily 4242 Created page with "Nuggets Winning Moves, 2003 designed by Christwart Conrad translated by Pitt Crandlemire Whoever digs others a goldmine... For 2 - 4 players from 8 years Gam..." wikitext text/x-wiki Nuggets Winning Moves, 2003 designed by Christwart Conrad translated by Pitt Crandlemire Whoever digs others a goldmine... For 2 - 4 players from 8 years Game material - 1 gameboard consisting of a 5x8 grid - 35 blockers - 8 gold mine markers showing the number of goldstrike points for that area - 4x16 chips with different numbers - 1 rules booklet Idea of the game Nuggets have been found in the Golden Valley! The gold diggers try to sell their claims to the big mining companies for as much as they can get by gathering as many Nuggets as possible. The players take on the role of prospectors and try through skillful placement of blockers to create valuable claims and then to control them with their high value chips. But the other players have not fallen on their heads and will compete for those claims quite lively, too If it all comes to naught, the claims are laid out once again. In the end, the one who walks away with the most money will be the one who bought up the most productive claims. Set-up The numbered stickers are stuck onto the gold mine markers and these are then placed on the board (see the illustration). Each player chooses a color and takes as many chips of that color in the appropriate value as indicated on the following table. He places these face-down in front of himself. In a 4-player game, players sitting opposite each other form a team. Chip-distribution total 1 point 2 points 3 points 4 points 5 points 2 players, each 16 11 2 1 1 1 3 players, each 11 7 2 1 1 - 4 players, each 8 5 1 1 1 - The Gold mine markers are placed on the gameboard as follows: (refer to illustration in German rules) The youngest player begins the first game. In future games, the player that lost the most recent game always starts. Course of the game Play goes clockwise. On his turn, a player must execute one of the following actions: EITHER build two blockers OR place a chip on an unoccupied space Build two blockers In each case, the player places a blocker on any one unoccupied line between 2 spaces. The blockers need not be placed adjacent to each other. Restriction: a player may not place a blocker such that an area of less than 4 spaces is completely enclosed. Note: it is possible that there may be several gold mine markers in an area or even none at all. Place a chip The player places one of his colored chips face-down on any one unoccupied space (not already containing a chip or a gold mine marker). He secretly chooses which of his numbered chips he wishes to place. Players should decide at the beginning of the game whether players will be allowed to look at their own chips after they've been played or whether they'll simply be required to remember the numbers after they've been played.. Partnership game Partners may communicate with each other in the 4-player game but they may not do so privately; the players on the other team must be able to see and hear everything. Also, partners may not show chips to each other. End of the game If a player has no more chips, he may still play blockers. Also, if there are no more blockers, a player may play his chips. Whenever a player can't or chooses not to play, he may pass but he may not then play again later. Once the last player has passed, the game ends. Scoring All chips are turned over. For each enclosed area, each player sums the points on his chips. The points of both partners are added together in the team game. The player with most points in an area gets all the gold mine markers in that area which score points equal to their value. Areas without gold mine markers score nothing. In the event of a tie in an area, the number of goldstrike points on the marker is divided among the tied players. (Half points are awarded when appropriate.) Whoever ultimately has acquired the most goldstrike points is able to mine the most gold Nuggets and wins the game. Variant Once you have become familiar with the game played according to the standard set-up, you can then try placing the gold mine markers differently in later games. 1e3776191a34e20407db27058f671a61b4d3281d 994 992 2013-11-29T05:32:37Z Stealthswor 3331 wikitext text/x-wiki '''Nuggets:''' Published by Winning Moves, 2003 - designed by Christwart Conrad - translated by Pitt Crandlemire '''Players''': For 2 - 4 players from 8 years '''Game material''': 1 gameboard consisting of a 5x8 grid, 35 blockers, 8 gold mine markers showing the number of goldstrike points for that area, 4x16 chips with different numbers, 1 rules booklet '''Idea of the game''': Nuggets have been found in the Golden Valley! The gold diggers try to sell their claims to the big mining companies for as much as they can get by gathering as many Nuggets as possible. The players take on the role of prospectors and try through skillful placement of blockers to create valuable claims and then to control them with their high value chips. But the other players have not fallen on their heads and will compete for those claims quite lively, too If it all comes to naught, the claims are laid out once again. In the end, the one who walks away with the most money will be the one who bought up the most productive claims. '''Set-up''': The numbered stickers are stuck onto the gold mine markers and these are then placed on the board (see the illustration). Each player chooses a color and takes as many chips of that color in the appropriate value as indicated on the following table. He places these face-down in front of himself. In a 4-player game, players sitting opposite each other form a team. '''Chip-distribution''': 2 players, each 16 11 2 1 1 1 3 players, each 11 7 2 1 1 - 4 players, each 8 5 1 1 1 - The Gold mine markers are placed on the gameboard as follows: (refer to illustration in German rules) The youngest player begins the first game. In future games, the player that lost the most recent game always starts. '''Course of the game''' Play goes clockwise. On his turn, a player must execute one of the following actions: ''EITHER'' build two blockers ''OR'' place a chip on an unoccupied space '''Build two blockers''': In each case, the player places a blocker on any one unoccupied line between 2 spaces. The blockers need not be placed adjacent to each other. Restriction: a player may not place a blocker such that an area of less than 4 spaces is completely enclosed. Note: it is possible that there may be several gold mine markers in an area or even none at all. '''Place a chip''': The player places one of his colored chips face-down on any one unoccupied space (not already containing a chip or a gold mine marker). He secretly chooses which of his numbered chips he wishes to place. Players should decide at the beginning of the game whether players will be allowed to look at their own chips after they've been played or whether they'll simply be required to remember the numbers after they've been played.. '''Partnership game''': Partners may communicate with each other in the 4-player game but they may not do so privately; the players on the other team must be able to see and hear everything. Also, partners may not show chips to each other. '''End of the game''': If a player has no more chips, he may still play blockers. Also, if there are no more blockers, a player may play his chips. Whenever a player can't or chooses not to play, he may pass but he may not then play again later. Once the last player has passed, the game ends. '''Scoring''': All chips are turned over. For each enclosed area, each player sums the points on his chips. The points of both partners are added together in the team game. The player with most points in an area gets all the gold mine markers in that area which score points equal to their value. Areas without gold mine markers score nothing. In the event of a tie in an area, the number of goldstrike points on the marker is divided among the tied players. (Half points are awarded when appropriate.) Whoever ultimately has acquired the most goldstrike points is able to mine the most gold Nuggets and wins the game. 51ef95683b6ec3869cac679e26a50fcba8afe0e2 995 994 2013-11-29T15:32:37Z Trzynastka 4332 wikitext text/x-wiki *********************************************************************************************************************************** '''''Game Nuggets is not the same as Armadora, it is only similar.''''' Proper rules: http://pl.boardgamearena.com/link?url=http%3A%2F%2Fcdn.boardgamearena.net%2Fdata%2Fnewsimg%2FArmadora_EN.pdf&id=1228 *********************************************************************************************************************************** '''Nuggets:''' Published by Winning Moves, 2003 - designed by Christwart Conrad - translated by Pitt Crandlemire '''Players''': For 2 - 4 players from 8 years '''Game material''': 1 gameboard consisting of a 5x8 grid, 35 blockers, 8 gold mine markers showing the number of goldstrike points for that area, 4x16 chips with different numbers, 1 rules booklet '''Idea of the game''': Nuggets have been found in the Golden Valley! The gold diggers try to sell their claims to the big mining companies for as much as they can get by gathering as many Nuggets as possible. The players take on the role of prospectors and try through skillful placement of blockers to create valuable claims and then to control them with their high value chips. But the other players have not fallen on their heads and will compete for those claims quite lively, too If it all comes to naught, the claims are laid out once again. In the end, the one who walks away with the most money will be the one who bought up the most productive claims. '''Set-up''': The numbered stickers are stuck onto the gold mine markers and these are then placed on the board (see the illustration). Each player chooses a color and takes as many chips of that color in the appropriate value as indicated on the following table. He places these face-down in front of himself. In a 4-player game, players sitting opposite each other form a team. '''Chip-distribution''': 2 players, each 16 11 2 1 1 1 3 players, each 11 7 2 1 1 - 4 players, each 8 5 1 1 1 - The Gold mine markers are placed on the gameboard as follows: (refer to illustration in German rules) The youngest player begins the first game. In future games, the player that lost the most recent game always starts. '''Course of the game''' Play goes clockwise. On his turn, a player must execute one of the following actions: ''EITHER'' build two blockers ''OR'' place a chip on an unoccupied space '''Build two blockers''': In each case, the player places a blocker on any one unoccupied line between 2 spaces. The blockers need not be placed adjacent to each other. Restriction: a player may not place a blocker such that an area of less than 4 spaces is completely enclosed. Note: it is possible that there may be several gold mine markers in an area or even none at all. '''Place a chip''': The player places one of his colored chips face-down on any one unoccupied space (not already containing a chip or a gold mine marker). He secretly chooses which of his numbered chips he wishes to place. Players should decide at the beginning of the game whether players will be allowed to look at their own chips after they've been played or whether they'll simply be required to remember the numbers after they've been played.. '''Partnership game''': Partners may communicate with each other in the 4-player game but they may not do so privately; the players on the other team must be able to see and hear everything. Also, partners may not show chips to each other. '''End of the game''': If a player has no more chips, he may still play blockers. Also, if there are no more blockers, a player may play his chips. Whenever a player can't or chooses not to play, he may pass but he may not then play again later. Once the last player has passed, the game ends. '''Scoring''': All chips are turned over. For each enclosed area, each player sums the points on his chips. The points of both partners are added together in the team game. The player with most points in an area gets all the gold mine markers in that area which score points equal to their value. Areas without gold mine markers score nothing. In the event of a tie in an area, the number of goldstrike points on the marker is divided among the tied players. (Half points are awarded when appropriate.) Whoever ultimately has acquired the most goldstrike points is able to mine the most gold Nuggets and wins the game. 00f0954786d3db52bede4c38c5d0ea55e2855d8b 999 995 2013-12-05T14:18:23Z Trzynastka 4332 wikitext text/x-wiki * '''''Game Nuggets is not the same as Armadora, it is only similar.''''' Proper rules: http://pl.boardgamearena.com/link?url=http%3A%2F%2Fcdn.boardgamearena.net%2Fdata%2Fnewsimg%2FArmadora_EN.pdf&id=1228 * '''Nuggets:''' Published by Winning Moves, 2003 - designed by Christwart Conrad - translated by Pitt Crandlemire '''Players''': For 2 - 4 players from 8 years '''Game material''': 1 gameboard consisting of a 5x8 grid, 35 blockers, 8 gold mine markers showing the number of goldstrike points for that area, 4x16 chips with different numbers, 1 rules booklet '''Idea of the game''': Nuggets have been found in the Golden Valley! The gold diggers try to sell their claims to the big mining companies for as much as they can get by gathering as many Nuggets as possible. The players take on the role of prospectors and try through skillful placement of blockers to create valuable claims and then to control them with their high value chips. But the other players have not fallen on their heads and will compete for those claims quite lively, too If it all comes to naught, the claims are laid out once again. In the end, the one who walks away with the most money will be the one who bought up the most productive claims. '''Set-up''': The numbered stickers are stuck onto the gold mine markers and these are then placed on the board (see the illustration). Each player chooses a color and takes as many chips of that color in the appropriate value as indicated on the following table. He places these face-down in front of himself. In a 4-player game, players sitting opposite each other form a team. '''Chip-distribution''': 2 players, each 16 11 2 1 1 1 3 players, each 11 7 2 1 1 - 4 players, each 8 5 1 1 1 - The Gold mine markers are placed on the gameboard as follows: (refer to illustration in German rules) The youngest player begins the first game. In future games, the player that lost the most recent game always starts. '''Course of the game''' Play goes clockwise. On his turn, a player must execute one of the following actions: ''EITHER'' build two blockers ''OR'' place a chip on an unoccupied space '''Build two blockers''': In each case, the player places a blocker on any one unoccupied line between 2 spaces. The blockers need not be placed adjacent to each other. Restriction: a player may not place a blocker such that an area of less than 4 spaces is completely enclosed. Note: it is possible that there may be several gold mine markers in an area or even none at all. '''Place a chip''': The player places one of his colored chips face-down on any one unoccupied space (not already containing a chip or a gold mine marker). He secretly chooses which of his numbered chips he wishes to place. Players should decide at the beginning of the game whether players will be allowed to look at their own chips after they've been played or whether they'll simply be required to remember the numbers after they've been played.. '''Partnership game''': Partners may communicate with each other in the 4-player game but they may not do so privately; the players on the other team must be able to see and hear everything. Also, partners may not show chips to each other. '''End of the game''': If a player has no more chips, he may still play blockers. Also, if there are no more blockers, a player may play his chips. Whenever a player can't or chooses not to play, he may pass but he may not then play again later. Once the last player has passed, the game ends. '''Scoring''': All chips are turned over. For each enclosed area, each player sums the points on his chips. The points of both partners are added together in the team game. The player with most points in an area gets all the gold mine markers in that area which score points equal to their value. Areas without gold mine markers score nothing. In the event of a tie in an area, the number of goldstrike points on the marker is divided among the tied players. (Half points are awarded when appropriate.) Whoever ultimately has acquired the most goldstrike points is able to mine the most gold Nuggets and wins the game. 0fd5e3724a47ed7d81f1689cd82c622ee19514e3 Contact us 0 9 993 139 2013-11-27T21:59:46Z Sourisdudesert 1 wikitext text/x-wiki '''Board Game Arena''' is located in France. == Contact e-mail == contact(at)boardgamearena.com We receive '''a lot''' of e-mails. Please do not send us an e-mail in any of these two cases: * If you want to report a bug, please do it in the [http://boardgamearena.com/#!bugs bug reporting system] * If you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile. == Postal address == G. Isabelli 19 bd république 92 260 Fontenay-aux-Roses FRANCE +33 6 17 25 80 34 980a98bd2ca063ac351422c896d84cf8920c62a0 996 993 2013-12-03T13:35:26Z Januszk0 3262 wikitext text/x-wiki '''Board Game Arena''' znajduje się we Francji. == Kontakt e-mail == contact(at)boardgamearena.com Otrzymujemy '''wiele''' e-maili. Prosimy nie wysyłać do nas e-mail w każdym z tych dwóch przypadków: * Jeśli chcesz zgłosić błąd, proszę zrobić to poprzez [http://boardgamearena.com/#!bugs System zgłaszania błędów] * Jeśli chcesz zgłosić gracza naruszającego zasady BGA, użyj przycisku "Zgłoś tego gracza" na jego/jej profilu. == Adres pocztowy == G. Isabelli 19 bd république 92 260 Fontenay-aux-Roses FRANCE +33 6 17 25 80 34 77f301b40cd095e78da87dc00bf3664ef39f8b38 Gamehelphex 0 139 1000 2013-12-07T04:58:53Z Kennyyy 4327 Created page with "====GOAL==== The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color). ====OPENING==== The first player..." wikitext text/x-wiki ====GOAL==== The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color). ====OPENING==== The first player places a first token on any cell of the board. The second player has then the choice between: *continue playing his current color (and thus place a second token anywhere on the board); *or decide to switch colors and keep the first move for him. In this case the first player plays another token with his new color. ====TURNS==== After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board. ====GAME ENDS==== The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie. ====VARIANTS==== The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays. 64c70a6a7b2646cee825432cab9587a99814c548 1001 1000 2013-12-07T04:59:35Z Kennyyy 4327 wikitext text/x-wiki ====GOAL==== The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color). ====OPENING==== The first player places a first token on any cell of the board. The second player has then the choice between: *continue playing his current color (and thus place a second token anywhere on the board); *or decide to switch colors and keep the first move for him. In this case the first player plays another token with his new color. ====TURNS==== After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board. ====GAME ENDS==== The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie. ====VARIANTS==== The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays. 38a20c50a816bc26f1dbc09c03711a1b96b2cb44 1002 1001 2013-12-07T05:00:27Z Kennyyy 4327 wikitext text/x-wiki ===GOAL=== The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color). ===OPENING=== The first player places a first token on any cell of the board. The second player has then the choice between: *continue playing his current color (and thus place a second token anywhere on the board); *or decide to switch colors and keep the first move for him. In this case the first player plays another token with his new color. ===TURNS=== After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board. ===GAME ENDS=== The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie. ===VARIANTS=== The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays. 0dbe66a3ee55bc0f448f3c6122e6f0e108827115 1003 1002 2013-12-07T05:21:26Z Kennyyy 4327 wikitext text/x-wiki The Hex game is a connection game independently invented by two mathematicians, Piet Hein and John Nash, respectively in 1942 and 1947. The interest of this game mainly lies on the contrast between the simplicity of its rules and the potential complexity of its strategy. Another interesting aspect is that the game can't end in a tie. ===GOAL=== The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color). ===OPENING=== The first player places a first token on any cell of the board. The second player has then the choice between: *continue playing his current color (and thus place a second token anywhere on the board); *or decide to switch colors and keep the first move for him. In this case the first player places another token with his new color. ===TURNS=== After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board. ===GAME ENDS=== The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie. ===VARIANTS=== The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays. 0c861842b852f6b5bcc5c19b2755d32b13bda7da 1006 1003 2013-12-07T05:23:50Z Kennyyy 4327 wikitext text/x-wiki ===INTRODUCTION=== The Hex game is a connection game independently invented by two mathematicians, Piet Hein and John Nash, respectively in 1942 and 1947. The interest of this game mainly lies on the contrast between the simplicity of its rules and the potential complexity of its strategy. Another interesting aspect is that the game can't end in a tie. ===GOAL=== The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color). ===OPENING=== The first player places a first token on any cell of the board. The second player has then the choice between: *continue playing his current color (and thus place a second token anywhere on the board); *or decide to switch colors and keep the first move for him. In this case the first player places another token with his new color. ===TURNS=== After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board. ===GAME ENDS=== The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie. ===VARIANTS=== The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays. 21e638b436f93d68a93d5e59dbeea8b6778508a3 1007 1006 2013-12-07T05:26:21Z Kennyyy 4327 wikitext text/x-wiki ===INTRODUCTION=== The Hex game is a connection game independently invented by two mathematicians, Piet Hein and John Nash, respectively in 1942 and 1947. The interest of this game mainly lies on the contrast between the simplicity of its rules and the potential complexity of its strategy. Another interesting aspect is that the game can't end in a tie. ===GOAL=== The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color). ===OPENING=== The first player places a first token on any cell of the board. The second player has then the choice between: *continue playing his current color (and thus place a second token anywhere on the board); *or decide to switch colors and keep the first move for him. In this case the first player places another token with his new color. ===TURNS=== After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board. ===GAME ENDS=== The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie. ===VARIANTS=== The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays. 67fcdd553674042e6c4fa1d29f0f0d75af0c10d8 1008 1007 2013-12-07T05:27:17Z Kennyyy 4327 wikitext text/x-wiki ===INTRODUCTION=== The Hex game is a connection game independently invented by two mathematicians, Piet Hein and John Nash, respectively in 1942 and 1947. The interest of the game mainly lies on the contrast between the simplicity of its rules and the potential complexity of its strategy. Another interesting aspect is that the game can't end in a tie. ===GOAL=== The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color). ===OPENING=== The first player places a first token on any cell of the board. The second player has then the choice between: *continue playing his current color (and thus place a second token anywhere on the board); *or decide to switch colors and keep the first move for him. In this case the first player places another token with his new color. ===TURNS=== After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board. ===GAME ENDS=== The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie. ===VARIANTS=== The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays. beddcbb667b6116e9af68afd6a17ecd86e092730 1014 1008 2013-12-09T14:15:39Z Kennyyy 4327 wikitext text/x-wiki ===INTRODUCTION=== Le jeu de Hex est un jeu de placement inventé indépendamment par deux mathématiciens, Piet Hein et John Nash, respectivement en 1942 et 1947. L’intérêt principal du jeu tiens a l'opposition entre la simplicité des règles et la complexité des stratégies mises en jeu. Qui plus est, le jeu ne peut finir en match nul, ce qui lui confère un autre aspect intéressant. ===OBJECTIF=== Pour chacun des joueurs le but du jeu est de créer une ligne de pions de sa couleur reliant ses deux cotes du plateau (de sa propre couleur également). ===OUVERTURE=== Le premier joueur joue un premier pion sur n'importe quelle case du plateau. Le second joueur a alors le choix entre: *continuer a jouer avec sa couleur sur n'importe quelle autre case du plateau; *ou décider d’échanger sa couleur avec son adversaire et de prendre le premier pion placé pour lui. Dans ce cas le premier joueur prend le prochain tour. ===TOURS=== Apres les deux premiers tours (voir OUVERTURE), chaque joueur joue un pion de sa couleur a son tour. Un pion peut-être placé sur n'importe quelle case libre du plateau. ===FIN=== Le jeu s’arrête lorsqu'un des joueur a créé une ligne continue antre ses deux cotes du plateau. Il ne peut y avoir d’égalité ou de jeu nul. ===VARIANTES=== Le jeu peut se jouer sur différentes tailles de plateau. Le 6x6 est a réserver aux débutant et permet d'apprendre facilement les règles et de repérer les premiers "motifs" de jeu. Le 11x11 est une taille classiquement jouée. Le 14x14 est la taille recommandée par John Nash, un des inventeur du jeu, tandis que le 15x15 permet des parties plus longues et potentiellement plus stratégiques. 6eb5ecead3656178d85c661827efabd26238db88 1016 1014 2013-12-11T07:05:32Z Trociu 3428 wikitext text/x-wiki ==Zasady gry== Gra toczy się na planszy w kształcie rombu, złożonej z sześciokątnych pól. Rozmiar planszy może się zmieniać, ale liczba pól na każdym z boków jest zawsze stała. Tradycyjnie pojedynki rozgrywa się na planszy 11×11. Każdy z dwóch graczy biorących udział w grze dysponuje kamieniami o odmiennych kolorach. Gracze na przemian układają kamienie na wolnych polach planszy, tak, aby sąsiadujące utworzyły nieprzerwany ciąg łączący boki planszy własnego koloru. Wygrywa ten z graczy, który ułoży taki ciąg jako pierwszy. Często stosuje się dodatkową zasadę, mówiącą, że gracz wykonujący ruch jako drugi zamiast położyć swój kamień na wolnym polu może 'przejąć' kamień przeciwnika, tzn. zamienić jego kamień na swój. Dotyczy to tylko drugiego ruchu w rozgrywce (pierwszego ruchu drugiego gracza). Ta zasada stosowana jest również tutaj. b370555bab4642ec2ba6750e7dbe8afa6ab09e24 1017 1016 2013-12-11T10:51:12Z Sourisdudesert 1 Reverted edits by [[Special:Contributions/Trociu|Trociu]] ([[User talk:Trociu|talk]]) to last revision by [[User:Kennyyy|Kennyyy]] wikitext text/x-wiki ===INTRODUCTION=== Le jeu de Hex est un jeu de placement inventé indépendamment par deux mathématiciens, Piet Hein et John Nash, respectivement en 1942 et 1947. L’intérêt principal du jeu tiens a l'opposition entre la simplicité des règles et la complexité des stratégies mises en jeu. Qui plus est, le jeu ne peut finir en match nul, ce qui lui confère un autre aspect intéressant. ===OBJECTIF=== Pour chacun des joueurs le but du jeu est de créer une ligne de pions de sa couleur reliant ses deux cotes du plateau (de sa propre couleur également). ===OUVERTURE=== Le premier joueur joue un premier pion sur n'importe quelle case du plateau. Le second joueur a alors le choix entre: *continuer a jouer avec sa couleur sur n'importe quelle autre case du plateau; *ou décider d’échanger sa couleur avec son adversaire et de prendre le premier pion placé pour lui. Dans ce cas le premier joueur prend le prochain tour. ===TOURS=== Apres les deux premiers tours (voir OUVERTURE), chaque joueur joue un pion de sa couleur a son tour. Un pion peut-être placé sur n'importe quelle case libre du plateau. ===FIN=== Le jeu s’arrête lorsqu'un des joueur a créé une ligne continue antre ses deux cotes du plateau. Il ne peut y avoir d’égalité ou de jeu nul. ===VARIANTES=== Le jeu peut se jouer sur différentes tailles de plateau. Le 6x6 est a réserver aux débutant et permet d'apprendre facilement les règles et de repérer les premiers "motifs" de jeu. Le 11x11 est une taille classiquement jouée. Le 14x14 est la taille recommandée par John Nash, un des inventeur du jeu, tandis que le 15x15 permet des parties plus longues et potentiellement plus stratégiques. 6eb5ecead3656178d85c661827efabd26238db88 1018 1017 2013-12-11T10:52:01Z Sourisdudesert 1 wikitext text/x-wiki ===INTRODUCTION=== The Hex game is a connection game independently invented by two mathematicians, Piet Hein and John Nash, respectively in 1942 and 1947. The interest of the game mainly lies on the contrast between the simplicity of its rules and the potential complexity of its strategy. Another interesting aspect is that the game can't end in a tie. ===GOAL=== The goal for each player is to create a connected path of his tokens linking his two opposite sides of the board (of his color). ===OPENING=== The first player places a first token on any cell of the board. The second player has then the choice between: *continue playing his current color (and thus place a second token anywhere on the board); *or decide to switch colors and keep the first move for him. In this case the first player places another token with his new color. ===TURNS=== After the first two moves (see OPENING), each player plays a token of his color on his turn. A token can be placed on any free cell of the board. ===GAME ENDS=== The game ends when one of the players has built a complete path with his tokens between his two sides of the board. The game can't end in a tie. ===VARIANTS=== The game can be played on several different board sizes. The 6x6 board is designed to help beginners to understand the basic rules and discover simple game patterns. The 11x11 board is a more classic size. The 14x14 board is the one recommended by John Nash, one of the game inventor, and the 15x15 allowed longer plays. beddcbb667b6116e9af68afd6a17ecd86e092730 Gamehelpquarto 0 140 1004 2013-12-07T05:21:34Z Sooz 4387 Created page with "Quarto is a simple abstract game that should take about 15 mins. to play. '''To win, complete a row of 4 pieces (horizontally, vertically, or diagonally) that share at least ..." wikitext text/x-wiki Quarto is a simple abstract game that should take about 15 mins. to play. '''To win, complete a row of 4 pieces (horizontally, vertically, or diagonally) that share at least one trait in common'''. The twist to the game is that you select the piece your opponent places on the board and vice versa. Pieces have 4 traits each which are a combination of the following: - Tall or Short - Dark or Light - Round or Square - Hollow or Solid 06255b5886333cb044a2c09873e72bf4d87658d4 1005 1004 2013-12-07T05:23:08Z Sooz 4387 wikitext text/x-wiki Quarto is a simple abstract game that should take about 15 mins. to play. '''To win, complete a row of 4 pieces (horizontally, vertically, or diagonally) that share at least one trait in common. The twist to the game is that you select the piece your opponent places on the board and vice versa.''' Pieces have 4 traits each which are a combination of the following: Tall or Short Dark or Light Round or Square Hollow or Solid f460fb16a46d83350325492ecd055c402e54c9a8 Game interface logic: yourgamename.js 0 88 1009 988 2013-12-08T02:50:31Z Kennyyy 4327 Specification about image preloading: don't need to specify for image boxes wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ).play(); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Reversi example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. '''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> bcb948111c1d9401116fc8dcab816d616cd5b6d4 Gamehelpthejellymonsterlab 0 141 1010 2013-12-09T13:06:02Z Adela82 4198 Created page with "In The Jelly Monster Lab you are an scientist trying to make the best jelly monsters. In order to do it so, you need to move through the labs, trying to find the parts you nee..." wikitext text/x-wiki In The Jelly Monster Lab you are an scientist trying to make the best jelly monsters. In order to do it so, you need to move through the labs, trying to find the parts you need to make your monsters. At the beginning, every player starts with two experiments. Every experiment shows a monster made with a colored body (blue, red, pink or gren), eyes (1, 2 or 3) and a mouth (happy or sad) and a lab where you must make it. The parts are spread out over the six labs, so you move to them, and grab the parts you need to make your monsters, but you cannot have more than 5 cards in your hand. Once you have your experiment card and the parts, move to the lab indicated by the experiment card and leave all there (the experiment card and the parts). When other player come to visit that lab, it'll find your monster and then, it will be yours. While you're moving through the labs, you're leaving trails in order to know which player has been the last visiting it. If you move to a lab with a trail, there may be a monster of the owner of the trail. In addition, you can't move to a lab you were the last visit, so you need to program your moves to have all the parts of the experiment before you arrive to the lab where you must leave it with all the parts in your hand. In any time, you may want to go to the center to pick up a new experiment and make new monsters. But you'll not be able to go to the center if you just came from there (your meeple shows laid down) and if you have the maximum cards in hand (five). When a player has 5 monsters done, the center is open to close the game. Any player who goes there, finishes the game. Every monster has an score on it, depending on how difficult is to find their parts. You can see how many parts are in the game of each type, and what are all the experiments in the guide card placed on the bottom left corner. The player with the most score points win the game. Advices: If you have experiments, one side too low scored, or on the other side too difficult to find the parts, you can leave the expèriment card in any lab, so other players can play with it, or maybe you can play with it in a later visit. ea8f82efbfe9ed3393312c857edc04e17a832170 1011 1010 2013-12-09T13:06:11Z Adela82 4198 wikitext text/x-wiki In The Jelly Monster Lab you are an scientist trying to make the best jelly monsters. In order to do it so, you need to move through the labs, trying to find the parts you need to make your monsters. At the beginning, every player starts with two experiments. Every experiment shows a monster made with a colored body (blue, red, pink or gren), eyes (1, 2 or 3) and a mouth (happy or sad) and a lab where you must make it. The parts are spread out over the six labs, so you move to them, and grab the parts you need to make your monsters, but you cannot have more than 5 cards in your hand. Once you have your experiment card and the parts, move to the lab indicated by the experiment card and leave all there (the experiment card and the parts). When other player come to visit that lab, it'll find your monster and then, it will be yours. While you're moving through the labs, you're leaving trails in order to know which player has been the last visiting it. If you move to a lab with a trail, there may be a monster of the owner of the trail. In addition, you can't move to a lab you were the last visit, so you need to program your moves to have all the parts of the experiment before you arrive to the lab where you must leave it with all the parts in your hand. In any time, you may want to go to the center to pick up a new experiment and make new monsters. But you'll not be able to go to the center if you just came from there (your meeple shows laid down) and if you have the maximum cards in hand (five). When a player has 5 monsters done, the center is open to close the game. Any player who goes there, finishes the game. Every monster has an score on it, depending on how difficult is to find their parts. You can see how many parts are in the game of each type, and what are all the experiments in the guide card placed on the bottom left corner. The player with the most score points win the game. Advices: If you have experiments, one side too low scored, or on the other side too difficult to find the parts, you can leave the expèriment card in any lab, so other players can play with it, or maybe you can play with it in a later visit. e3493b9fd52feb5d855a879718adb71b39011ae6 1012 1011 2013-12-09T13:12:21Z Adela82 4198 wikitext text/x-wiki In The Jelly Monster Lab you are an scientist trying to make the best jelly monsters. In order to do it so, you need to move through the labs, trying to find the parts you need to make your monsters. At the beginning, every player starts with two experiments. Every experiment shows a monster made with a colored body (blue, red, pink or gren), eyes (1, 2 or 3) and a mouth (happy or sad) and a lab where you must make it. The parts are spread out over the six labs, so you move to them, and grab the parts you need to make your monsters, but you cannot have more than 5 cards in your hand. Once you have your experiment card and the parts, move to the lab indicated by the experiment card and leave all there (the experiment card and the parts). When other player come to visit that lab, it'll find your monster and then, it will be yours. While you're moving through the labs, you're leaving trails in order to know which player has been the last visiting it. If you move to a lab with a trail, there may be a monster of the owner of the trail. In addition, you can't move to a lab you were the last visit, so you need to program your moves to have all the parts of the experiment before you arrive to the lab where you must leave it with all the parts in your hand. In any time, you may want to go to the center to pick up a new experiment and make new monsters. But you'll not be able to go to the center if you just came from there (your meeple shows laid down) and if you have the maximum cards in hand (five). When a player has 4 monsters done, the center is open to close the game. Any player who goes there, finishes the game. Every monster has an score on it, depending on how difficult is to find their parts. You can see how many parts are in the game of each type, and what are all the experiments in the guide card placed on the bottom left corner. The player with the most score points win the game. Advices: If you have experiments, one side too low scored, or on the other side too difficult to find the parts, you can leave the expèriment card in any lab, so other players can play with it, or maybe you can play with it in a later visit. f1283bc465bc59648625e6db6744eadef7312970 1013 1012 2013-12-09T13:13:29Z Adela82 4198 wikitext text/x-wiki In The Jelly Monster Lab you are an scientist trying to make the best jelly monsters. In order to do it so, you need to move through the labs, trying to find the parts you need to make your monsters. At the beginning, every player starts with two experiments. Every experiment shows a monster made with a colored body (blue, red, pink or gren), eyes (1, 2 or 3) and a mouth (happy or sad) and a lab where you must make it. The parts are spread out over the six labs, so you move to them, and grab the parts you need to make your monsters, but you cannot have more than 5 cards in your hand. Once you have your experiment card and the parts, move to the lab indicated by the experiment card and leave all there (the experiment card and the parts). When other player come to visit that lab, it'll find your monster and then, it will be yours. While you're moving through the labs, you're leaving trails in order to know which player has been the last visiting it. If you move to a lab with a trail, there may be a monster of the owner of the trail. In addition, you can't move to a lab you were the last visit, so you need to program your moves to have all the parts of the experiment before you arrive to the lab where you must leave it with all the parts in your hand. In any time, you may want to go to the center to pick up a new experiment and make new monsters. But you'll not be able to go to the center if you just came from there (your meeple shows laid down) and if you have the maximum cards in hand (five). When a player has 4 monsters done, the center is open to close the game. Any player who goes there, finishes the game. Every monster has an score on it, depending on how difficult is to find their parts. You can see how many parts are in the game of each type, and what are all the experiments in the guide card placed on the bottom left corner of the playboard. The player with the most score points win the game. Advices: If you have experiments, one side too low scored, or on the other side too difficult to find the parts, you can leave the expèriment card in any lab, so other players can play with it, or maybe you can play with it in a later visit. 1665b014e042e0a25ddc91de3c09a9b522506855 1019 1013 2013-12-11T22:18:42Z Trociu 3428 wikitext text/x-wiki ==Cel gry== Zdobyć jak najwięcej punktów za stworzone potwory ==Tworzenie potwora== Każdy potwór składa się z: - oczu: może mieć jedno, dwoje lub troje oczu - buzi: może mieć uśmiech albo grymas - ciała: może być czerwone, zielone, różowe bądź niebieskie Każdy potwór tworzony jest też w jednym, konkretnym laboratorium (z 6 dostępnych). Każda część potwora występują w określenie ilości i widać to na ściądze. Liczba punktów to cyfra w gwiazdce - zarazem oznacza jak trudno jest takiego potwora złożyć (tzn. na im mniej pospolitych fragmentach bazuje). ==Zasady gry== Gracze na zmiany wykonują swoje tury. W czasie swojej tury gracz musi przemieścić się do sąsiedniego laboratorium (z wyjątkiem tych w których już był - określa to żeton w kolorze gracza) lub do środkowej talii talii. Środkowa talia to talia eksperymentów, więc wejście tam wiąże się zawsze z pociągnięciem dodatkowej karty eksperymentu. Jeżeli gracz ma już 5 kart na ręce to nie może tam wejsc (jest to limit kart na ręce). Jeżeli nie może też pójść do innego laboratorium zmuszony jest pozostawić jedną kartę w laboratorium, w którym się znajduje i tym samym traci kolejkę. Gracz, który wchodzi do laboratorium może między nim a swoją ręką przenosić dowolną ilość kart pamiętając o limicie kart na ręce (5 kart). Mogą to być zarówno karty eksperymentów jak i części potwora. Aby stworzyć potwora gracz musi w odpowiednim laboratorium zostawić zarówno części potwora jak i kartę eksperymentu. Potwór jest stworzony dopiero w momencie kiedy inny gracz odwiedzi to laboratorium (po to m.in są znaczniki śladu - by zaznaczyć kto był ostatnio i być może stworzył potwora). Po stworzeniu potwora kartę eksperymentu przekazuje się twórcy (osobie, która ją tam umieściła) i stanowi ona jego punkty. CZĘŚCI POTWORA ZOSTAJĄ W LABORATORIUM I MOŻNA JE WYKORZYSTAĆ NAWET W TEJ SAMEJ TURZE DO STWORZENIA POTWORA! ==Koniec gry== Jeżeli ktoś stworzy 4 potwory (lub więcej - zależne od ustawień stołu) to od tego momentu gra się kończy po turze gracza, który wszedł na środkowy stos. Punkty to cyfry w gwiazdkach i na ich podstawie określa się zwycięzcę. fb8575a9882d5d5fac24591bc1c4a5659306159c 1020 1019 2013-12-12T19:25:32Z Trociu 3428 wikitext text/x-wiki In The Jelly Monster Lab you are an scientist trying to make the best jelly monsters. In order to do it so, you need to move through the labs, trying to find the parts you need to make your monsters. At the beginning, every player starts with two experiments. Every experiment shows a monster made with a colored body (blue, red, pink or gren), eyes (1, 2 or 3) and a mouth (happy or sad) and a lab where you must make it. The parts are spread out over the six labs, so you move to them, and grab the parts you need to make your monsters, but you cannot have more than 5 cards in your hand. Once you have your experiment card and the parts, move to the lab indicated by the experiment card and leave all there (the experiment card and the parts). When other player come to visit that lab, it'll find your monster and then, it will be yours. While you're moving through the labs, you're leaving trails in order to know which player has been the last visiting it. If you move to a lab with a trail, there may be a monster of the owner of the trail. In addition, you can't move to a lab you were the last visit, so you need to program your moves to have all the parts of the experiment before you arrive to the lab where you must leave it with all the parts in your hand. In any time, you may want to go to the center to pick up a new experiment and make new monsters. But you'll not be able to go to the center if you just came from there (your meeple shows laid down) and if you have the maximum cards in hand (five). When a player has 4 monsters done, the center is open to close the game. Any player who goes there, finishes the game. Every monster has an score on it, depending on how difficult is to find their parts. You can see how many parts are in the game of each type, and what are all the experiments in the guide card placed on the bottom left corner of the playboard. The player with the most score points win the game. Advices: If you have experiments, one side too low scored, or on the other side too difficult to find the parts, you can leave the expèriment card in any lab, so other players can play with it, or maybe you can play with it in a later visit. 1665b014e042e0a25ddc91de3c09a9b522506855 Gamehelpraceforthegalaxy 0 41 1015 843 2013-12-11T06:01:20Z Sooz 4387 wikitext text/x-wiki In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments. There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins. You may drag a resource (single-coloured small card) to a consumption power to consume it. '''Summary of Goods''' Yellow = Alien Tech Green = Genes Brown = Rare Elements Blue = Novelty Goods '''Summary of Phases''' Explore = draw 2 cards; keep 1, discard the other Develop = place and pay for a development Settle = place and pay for a world, receiving any windfall as indicated Consume = use consume powers if possible, typically to discard goods for victory point chips Produce = place a good on each world without a good that produces one 38dad590c7c548f8bc06cb4fe31ff392cc69d862 1029 1015 2014-01-06T07:51:31Z Drchinchilla 4623 wikitext text/x-wiki In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments. There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins. You may drag a resource (single-coloured small card) to a consumption power to consume it. '''Summary of Goods''' Yellow = Alien Tech Green = Genes Brown = Rare Elements Blue = Novelty Goods '''Summary of Phases''' Explore = draw 2 cards; keep 1, discard the other Develop = place and pay for a development Settle = place and pay for a world, receiving any windfall as indicated Consume = use consume powers if possible, typically to discard goods for victory point chips Produce = place a good on each world without a good that produces one '''Phase Bonuses''' Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card Develop = discard 1 less card when paying for the development Settle = draw 1 card after settling a world Consume = Gain double victory points for consumed goods OR trade by discarding a card from your hand to draw new cards (bonuses from $ row apply) Produce = Produce a good on one windfall world that does not already have a good b9a76b03a12de68b52a18216d1315508178cd908 1030 1029 2014-01-06T07:52:19Z Drchinchilla 4623 wikitext text/x-wiki In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments. There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins. You may drag a resource (single-coloured small card) to a consumption power to consume it. '''Summary of Goods''' Yellow = Alien Tech Green = Genes Brown = Rare Elements Blue = Novelty Goods '''Summary of Phases''' Explore = draw 2 cards; keep 1, discard the other Develop = place and pay for a development Settle = place and pay for a world, receiving any windfall as indicated Consume = use consume powers if possible, typically to discard goods for victory point chips Produce = place a good on each world without a good that produces one '''Phase Bonuses''' These are the bonuses you gain for choosing each phase: Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card Develop = discard 1 less card when paying for the development Settle = draw 1 card after settling a world Consume = Gain double victory points for consumed goods OR trade by discarding a card from your hand to draw new cards (bonuses from $ row apply) Produce = Produce a good on one windfall world that does not already have a good 82a71cf988b934c0e3883288700b4fae9c846cb1 1031 1030 2014-01-06T07:52:29Z Drchinchilla 4623 wikitext text/x-wiki In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments. There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins. You may drag a resource (single-coloured small card) to a consumption power to consume it. '''Summary of Goods''' Yellow = Alien Tech Green = Genes Brown = Rare Elements Blue = Novelty Goods '''Summary of Phases''' Explore = draw 2 cards; keep 1, discard the other Develop = place and pay for a development Settle = place and pay for a world, receiving any windfall as indicated Consume = use consume powers if possible, typically to discard goods for victory point chips Produce = place a good on each world without a good that produces one '''Phase Bonuses''' These are the bonuses you gain for choosing each phase: Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card Develop = discard 1 less card when paying for the development Settle = draw 1 card after settling a world Consume = Gain double victory points for consumed goods OR trade by discarding a card from your hand to draw new cards (bonuses from $ row apply) Produce = Produce a good on one windfall world that does not already have a good 70967f57bb4d0ff1597fccbd5e6877e460d9bb48 1032 1031 2014-01-06T08:01:38Z Drchinchilla 4623 wikitext text/x-wiki In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments. There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins. You may drag a resource (single-coloured small card) to a consumption power to consume it. '''Summary of Goods''' Yellow = Alien Tech Green = Genes Brown = Rare Elements Blue = Novelty Goods '''Summary of Phases''' Explore = draw 2 cards; keep 1, discard the other Develop = place and pay for a development Settle = place and pay for a world, receiving any windfall as indicated Consume = use consume powers if possible, typically to discard goods for victory point chips Produce = place a good on each world without a good that produces one '''Phase Bonuses''' These are the bonuses you gain for choosing each phase: Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card Develop = discard 1 less card when paying for the development Settle = draw 1 card after settling a world Consume = Gain double victory points for consumed goods OR trade by discarding a card from your hand to draw new cards (bonuses from $ row apply) Produce = Produce a good on one windfall world that does not already have a good 1f7c743a1f6a43edfe085a83425cb51510c5e563 1033 1032 2014-01-06T08:17:40Z Drchinchilla 4623 wikitext text/x-wiki In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments. There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins. You may drag a resource (single-coloured small card) to a consumption power to consume it. '''Summary of Goods''' Yellow = Alien Tech Green = Genes Brown = Rare Elements Blue = Novelty Goods '''Summary of Phases''' Explore = draw 2 cards; keep 1, discard the other Develop = place and pay for a development Settle = place and pay for a world, receiving any windfall as indicated Consume = use consume powers if possible, typically to discard goods for victory point chips Produce = place a good on each world without a good that produces one '''Phase Bonuses''' These are the bonuses you gain for choosing each phase: Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card Develop = discard 1 less card when paying for the development Settle = draw 1 card after settling a world Consume = Gain double victory points for consumed goods OR trade by discarding a card from your hand to draw new cards (bonuses from $ row apply) Produce = Produce a good on one windfall world that does not already have a good 5bdb5660524e4b8f45c515073c8005e7172effdd 1034 1033 2014-01-06T08:17:56Z Drchinchilla 4623 wikitext text/x-wiki In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments. There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins. You may drag a resource (single-coloured small card) to a consumption power to consume it. '''Summary of Goods''' Yellow = Alien Tech Green = Genes Brown = Rare Elements Blue = Novelty Goods '''Summary of Phases''' Explore = draw 2 cards; keep 1, discard the other Develop = place and pay for a development Settle = place and pay for a world, receiving any windfall as indicated Consume = use consume powers if possible, typically to discard goods for victory point chips Produce = place a good on each world without a good that produces one '''Phase Bonuses''' These are the bonuses you gain for choosing each phase: Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card Develop = discard 1 less card when paying for the development Settle = draw 1 card after settling a world Consume = Gain double victory points for consumed goods OR trade by discarding a card from /nyour hand to draw new cards (bonuses from $ row apply) Produce = Produce a good on one windfall world that does not already have a good 733712790d9a029ae02283aa7855f2904fc26c0d 1035 1034 2014-01-06T08:18:21Z Drchinchilla 4623 wikitext text/x-wiki In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments. There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins. You may drag a resource (single-coloured small card) to a consumption power to consume it. '''Summary of Goods''' Yellow = Alien Tech Green = Genes Brown = Rare Elements Blue = Novelty Goods '''Summary of Phases''' Explore = draw 2 cards; keep 1, discard the other Develop = place and pay for a development Settle = place and pay for a world, receiving any windfall as indicated Consume = use consume powers if possible, typically to discard goods for victory point chips Produce = place a good on each world without a good that produces one '''Phase Bonuses''' These are the bonuses you gain for choosing each phase: Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card Develop = discard 1 less card when paying for the development Settle = draw 1 card after settling a world Consume = Gain double victory points for consumed goods OR trade by discarding a card from your hand to draw new cards (bonuses from $ row apply) Produce = Produce a good on one windfall world that does not already have a good 5bdb5660524e4b8f45c515073c8005e7172effdd 1036 1035 2014-01-06T08:39:16Z Drchinchilla 4623 wikitext text/x-wiki In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments. There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins. You may drag a resource (single-coloured small card) to a consumption power to consume it. '''Summary of Goods''' Yellow = Alien Tech Green = Genes Brown = Rare Elements Blue = Novelty Goods '''Summary of Phases''' Explore = draw 2 cards; keep 1, discard the other Develop = place and pay for a development Settle = place and pay for a world, receiving any windfall as indicated Consume = use consume powers if possible, typically to discard goods for victory point chips Produce = place a good on each world without a good that produces one '''Phase Bonuses''' These are the bonuses you gain for choosing each phase: Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card Develop = discard 1 less card when paying for the development Settle = draw 1 card after settling a world Consume = Gain double victory points for consumed goods OR trade by discarding a card from your hand to draw new cards (bonuses from $ row apply) Produce = Produce a good on one windfall world that does not already have a good 1f2c804430fd2d2c4d65bc03523df7b5c9742cac 1037 1036 2014-01-06T08:39:50Z Drchinchilla 4623 wikitext text/x-wiki In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments. There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins. You may drag a resource (single-coloured small card) to a consumption power to consume it. '''Summary of Goods''' Yellow = Alien Tech (5) Green = Genes (4) Brown = Rare Elements (3) Blue = Novelty Goods (2) '''Summary of Phases''' Explore = draw 2 cards; keep 1, discard the other Develop = place and pay for a development Settle = place and pay for a world, receiving any windfall as indicated Consume = use consume powers if possible, typically to discard goods for victory point chips Produce = place a good on each world without a good that produces one '''Phase Bonuses''' These are the bonuses you gain for choosing each phase: Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card Develop = discard 1 less card when paying for the development Settle = draw 1 card after settling a world Consume = Gain double victory points for consumed goods OR trade by discarding a card from your hand to draw new cards (bonuses from $ row apply) Produce = Produce a good on one windfall world that does not already have a good acb372225d62f3f811ece974356cadefdbcf1dc3 1038 1037 2014-01-06T08:40:34Z Drchinchilla 4623 wikitext text/x-wiki In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments. There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins. You may drag a resource (single-coloured small card) to a consumption power to consume it. '''Summary of Goods''' Yellow = Alien Tech (5) Green = Genes (4) Brown = Rare Elements (3) Blue = Novelty Goods (2) '''Summary of Phases''' Explore = draw 2 cards; keep 1, discard the other Develop = place and pay for a development Settle = place and pay for a world, receiving any windfall as indicated Consume = use consume powers if possible, typically to discard goods for victory point chips Produce = place a good on each world without a good that produces one '''Phase Bonuses''' These are the bonuses you gain for choosing each phase: Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card Develop = discard 1 less card when paying for the development Settle = draw 1 card after settling a world Consume = Gain double victory points for consumed goods OR trade by discarding a resource from your hand to draw cards equal to its trade value (bonuses from $ row apply) Produce = Produce a good on one windfall world that does not already have a good ca32e154d43da007610ffa53f4b079f5154805e4 1039 1038 2014-01-06T08:42:03Z Drchinchilla 4623 wikitext text/x-wiki In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods and from bonuses from special developments. There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 cards and a new round begins. The game continues until one player played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins. You may drag a resource (single-coloured small card) to a consumption power to consume it. '''Summary of Goods''' Yellow = Alien Tech (trade value = 5) Green = Genes (4) Brown = Rare Elements (3) Blue = Novelty Goods (2) '''Summary of Phases''' Explore = draw 2 cards; keep 1, discard the other Develop = place and pay for a development Settle = place and pay for a world, receiving any windfall as indicated Consume = use consume powers if possible, typically to discard goods for victory point chips Produce = place a good on each world without a good that produces one '''Phase Bonuses''' These are the bonuses you gain for choosing each phase: Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card Develop = discard 1 less card when paying for the development Settle = draw 1 card after settling a world Consume = Gain double victory points for consumed goods OR trade by discarding a resource from your hand to draw cards equal to its trade value (bonuses from $ row apply) Produce = Produce a good on one windfall world that does not already have a good d7a783556bd5db9c8aebfe061b5b77ac0f4570b0 Contact us 0 9 1021 996 2013-12-18T21:14:23Z Een 3 Reverted edits by [[Special:Contributions/Januszk0|Januszk0]] ([[User talk:Januszk0|talk]]) to last revision by [[User:Sourisdudesert|Sourisdudesert]] wikitext text/x-wiki '''Board Game Arena''' is located in France. == Contact e-mail == contact(at)boardgamearena.com We receive '''a lot''' of e-mails. Please do not send us an e-mail in any of these two cases: * If you want to report a bug, please do it in the [http://boardgamearena.com/#!bugs bug reporting system] * If you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile. == Postal address == G. Isabelli 19 bd république 92 260 Fontenay-aux-Roses FRANCE +33 6 17 25 80 34 980a98bd2ca063ac351422c896d84cf8920c62a0 Gamehelptakenoko 0 104 1022 697 2013-12-22T11:40:22Z Samc1078 4475 Re-wording of the Wind Action. wikitext text/x-wiki Quick Reference Guide Each turn consists of 2 steps: 1) Determine weather 2) Perform 2 different actions and complete objectives Weather Types (always optional) Sun - take a 3rd action Rain - grow 1 bamboo on any irrigated plot Wind - "may" take two identical actions this turn Storm - move panda to any plot and he eats a bamboo as normal Clouds - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather for this turn Improvements can only be placed on plots with no bamboo. There can only be 1 improvement on a plot and once placed cannot be changed. Irrigation channels must be between two plots. When a plot is irrigated for the first time it grows bamboo. Plots can only be placed adjacent to the pond or where it is next to 2 other plots in play. The gardener grows bamboo on his plot and all adjacent irrigated plots of the same color. Game ends when a certain number of objectives have been completed. 2 players - 9 objectives 3 players - 8 objectives 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. 2cd92079359df73e8679ce2711f60b62d4f58bfe Gamehelpacquire 0 142 1023 2013-12-23T19:08:08Z Scooby rex 4486 Created page with "The main object of Acquire is to become the wealthiest player by the end of the game. This is done by forming hotel chains, shrewdly buying the right stock at the right time,..." wikitext text/x-wiki The main object of Acquire is to become the wealthiest player by the end of the game. This is done by forming hotel chains, shrewdly buying the right stock at the right time, merging chains to obtain capital and adding hotels to the chains in which you have controlling interest to increase their value. At the beginning of the game, each player receives $6,000. To determine who plays first, each player draws one tile (representing a hotel) and places it in its matching square on the board. (No chains are formed at this time.) The player who has drawn the lowest number-letter combination starts play. Each player draws six hotels from the central cluster of face-down tiles on the table and keeps them in his/her "hand", not allowing other players to see them. Each player’s turn consists of: 1. Placing one of his hotel tiles on its matching square on the board. If this hotel creates a chain or causes a merger, all transactions connected with Creating Chains or Merging Chains are completed before the player’s turn continues. 2. Buying Stock. If, after placing his hotel, there are one or more hotel chains on the board, the player may, if he wishes, buy stock in one or more of them. (See Buying Stock). 3. Drawing another hotel tile to replace the one played. CREATING NEW CHAINS When a player places a hotel tile next to one already on the board (rank or file—not diagonally), a chain is created. For example, hotel tiles A1 and B2 are on the board but do not form a chain as they adjoin diagonally (not rank or file). Assume that among his six hotels, a player has C2 and B1. He places C2, creating a two-hotel chain. (If he had placed B1, he would have created a three-hotel chain; see above diagram.) Then assume that, on his next turn, he places B1, expanding the chain to four hotels. The maker of a chain chooses its name from seven possible chains, taking the appropriate chain marker and placing it atop any one hotel in the chain. He then receives a "Founder’s Bonus" of one free stock in that chain. A maximum of seven chains may be on the board at one time. Any hotel which would create an eighth chain may not be placed. MERGING CHAINS When a player places a hotel adjacent to two (or more) chains, a merger takes place. The chain with more member hotels takes over the other(s). If the chains are the same size before the merging hotel was placed, the person who made the merger chooses which chain takes over. The chain marker of the now defunct chain is removed. (See below, at Multiple Mergers, for what to do when placing one hotel that merges more than one chain). A chain containing 11 or more hotels is "safe" and cannot be taken over by another chain. A player may not place a hotel which would merge two safe chains. A safe chain may still take over an open chain, however. MAJORITY HOLDER'S BONUS. At merger time, bonuses are paid to the two largest shareholders in the defunct chain. In the case of a tie for the title of largest shareholder, the first and second bonuses are combined and divided equally between the tying shareholders. In the case of a tie for the title of second largest shareholder, the second bonus is divided equally between the tying players. If only one player holds stock in the defunct chain, he receives both bonuses. DISPOSAL OF STOCK AT TIME OF MERGER. After the bonuses have been paid, each player, starting with the merger maker and continuing clockwise, handles his/her stock in the defunct chain in one or more of the following ways: 1. Hold: Stock may be held in expectation of starting another chain with that name. 2. Sell: Stock may be sold to Stock Market at a price determined by the number of hotels in the defunct chain before the merger. 3. Trade: Stock may be traded at the rate of two blocks of defunct stock for one block of controlling chain stock. (If the Stock Market has no remaining blocks of controlling chain stock, players may not trade). MULTIPLE MERGERS. When multiple mergers (mergers of more than two chains at once) occur, the larger chain takes over all smaller chains simultaneously. The multiple merger is then handled as individual mergers. Majority holder’s bonuses are paid for the larger of defunct chains and players dispose of their stock in this chain. Then the smaller defunct chain is handled in the same manner. In the case of a tie, the merger maker chooses which defunct chain is to be handled first. Bonuses and stock prices are determined by the number of hotels in the defunct chain before the merger. BUYING STOCK Any player, immediately after playing his hotel, may buy stock in any active chain—up to a maximum of three blocks in any one turn. If he is unable to place any of his hotels, he may still buy stock. His purchase may be in one, two or three different chains. Price per block varies with the number of hotels in the chain. A player who runs out of money cannot buy stock but must place a hotel if he is able. He cannot raise money by selling stock except during the designated disposal period after a merger. Trading and selling of stock between players is not permitted. At any time, player may ask how much stock remains in a particular chain. ENDING THE GAME The game ends when one player, during his turn, announces that either all chains on board are "safe" or that any one chain contains 41 or more hotels. A player does not have to announce that the game is over if it is to his advantage to continue playing. After announcing that the game is over, the player may still complete his turn. To determine the winner, all chains are bought out by the bank. Majority holder’s bonuses are paid for all active chains. All players sell their stock. Stock in a chain that is not on the board is worthless. The player with the most money is the winner. 6daccd417644006bb74530f1659ad57b06feb515 Gamehelpsaboteur 0 32 1024 85 2014-01-03T13:59:28Z Tomcio8802 4596 /* Available variants */ wikitext text/x-wiki == Goal == Get as many gold nuggets as possible during the three rounds of the game. In order to do so, # if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards # if you are a '''saboteur''', you must, in association with other saboteurs, prevent the gold diggers from getting to the treasure. Your role (gold digger or saboteur) will be randomly selected at the start of each round. == Rules summary == On your turn, you must click on a card from your hand to select it, then play this card or discard it. You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card. The cards are of several types: * 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card. * 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score). * 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you. * 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about. * 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove. == Cards in play == * 44 'Path' cards * 9 'Sabotage' cards (three for each tool) * 6 'Repair a tool' cards (two for each tool) * 3 'Repair a tool among these two' cards (one for each combination of two tools) * 5 'Map' cards (one less than in the box set, as requested by the game author) * 3 'Rock fall' cards * 28 'Gold' cards ** 16 with one gold nugget ** 8 with two gold nuggets ** 4 with three gold nuggets == Roles == Roles are randomly selected among a set that depends upon the number of players: * with 3 players: 1 saboteur and 3 gold diggers * with 4 players: 1 saboteur and 4 gold diggers * with 5 players: 2 saboteurs and 4 gold diggers * with 6 players: 2 saboteurs and 5 gold diggers * with 7 players: 3 saboteurs and 5 gold diggers * with 8 players: 3 saboteurs and 6 gold diggers * with 9 players: 3 saboteurs and 7 gold diggers * with 10 players: 4 saboteurs and 7 gold diggers == Available variants == The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum! Two variants are about gold sharing: * '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed! * '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!) Two variants are about gameplay: * '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose! * '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded) '''Have a good game !''' The Official Anthem of Saboteur designed by '''Dzikidon''' Music - '''Adele - Skyfall''': *This is the end *Hold your breath and count to ten *Feel the Earth move and then *Hear your axe burst again *For this is the end *I’ve digged and dreamt this moment *I will repair I owe them *Even tho' I’m broken *Let the rock fall *When it crumbles *We will stand tall *Face it all together *Let the rock fall *When it crumbles *We will stand tall *Face it all together *At rock fall *At rock fall *Rock fall is where we start *A thousand miles and cards apart *Where roads collide and caves are dark *You may fix my trolley *You can break my lamp *But you’ll never have my gold *Let the rock fall (Let the rock fall) *When it crumbles (When it crumbles) *We will stand tall (We will stand tall) *Face it all together *Let the rock fall (Let the rock fall) *When it crumbles (When it crumbles) *We will stand tall (We will stand tall) *Face it all together *At rock fall *(Let the rock fall) *When it crumbles *We will stand tall) / x2 *Where you go I go *What you see I see *I know I'd never be me *Without the security *Of your fixing cards *Keeping me from harm *Put your end in their straight *And we'll stand *Let the rock fall (Let the rock fall) *When it crumbles (When it crumbles) *We will stand tall (We will stand tall) *Face it all together *Let the rock fall (Let the rock fall) *When it crumbles (When it crumbles) *We will stand tall (We will stand tall) *Face it all together *At rock fall *Let the rock fall *We will stand tall *At rock faaall a26d5ddfd4f3a8f6cb5a00a894689eba87be1aeb 1025 1024 2014-01-03T15:40:21Z Dzikidon 4598 wikitext text/x-wiki == Goal == Get as many gold nuggets as possible during the three rounds of the game. In order to do so, # if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards # if you are a '''saboteur''', you must, in association with other saboteurs, prevent the gold diggers from getting to the treasure. Your role (gold digger or saboteur) will be randomly selected at the start of each round. == Rules summary == On your turn, you must click on a card from your hand to select it, then play this card or discard it. You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card. The cards are of several types: * 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card. * 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score). * 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you. * 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about. * 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove. == Cards in play == * 44 'Path' cards * 9 'Sabotage' cards (three for each tool) * 6 'Repair a tool' cards (two for each tool) * 3 'Repair a tool among these two' cards (one for each combination of two tools) * 5 'Map' cards (one less than in the box set, as requested by the game author) * 3 'Rock fall' cards * 28 'Gold' cards ** 16 with one gold nugget ** 8 with two gold nuggets ** 4 with three gold nuggets == Roles == Roles are randomly selected among a set that depends upon the number of players: * with 3 players: 1 saboteur and 3 gold diggers * with 4 players: 1 saboteur and 4 gold diggers * with 5 players: 2 saboteurs and 4 gold diggers * with 6 players: 2 saboteurs and 5 gold diggers * with 7 players: 3 saboteurs and 5 gold diggers * with 8 players: 3 saboteurs and 6 gold diggers * with 9 players: 3 saboteurs and 7 gold diggers * with 10 players: 4 saboteurs and 7 gold diggers == Available variants == The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum! Two variants are about gold sharing: * '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed! * '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!) Two variants are about gameplay: * '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose! * '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded) '''Have a good game !''' The Official Anthem of Saboteur designed by '''Dzikidon''' and '''Sikora8a''' Music - '''Adele - Skyfall''': *This is the end *Hold your breath and count to ten *Feel the Earth move and then *Hear your axe burst again *For this is the end *I’ve digged and dreamt this moment *I will repair I owe them *Even tho' I’m broken *Let the rock fall *When it crumbles *We will stand tall *Face it all together *Let the rock fall *When it crumbles *We will stand tall *Face it all together *At rock fall *At rock fall *Rock fall is where we start *A thousand miles and cards apart *Where roads collide and caves are dark *You may fix my trolley *You can break my lamp *But you’ll never have my gold *Let the rock fall (Let the rock fall) *When it crumbles (When it crumbles) *We will stand tall (We will stand tall) *Face it all together *Let the rock fall (Let the rock fall) *When it crumbles (When it crumbles) *We will stand tall (We will stand tall) *Face it all together *At rock fall *(Let the rock fall) *When it crumbles *We will stand tall) / x2 *Where you go I go *What you see I see *I know I'd never be me *Without the security *Of your fixing cards *Keeping me from harm *Put your end in their straight *And we'll stand *Let the rock fall (Let the rock fall) *When it crumbles (When it crumbles) *We will stand tall (We will stand tall) *Face it all together *Let the rock fall (Let the rock fall) *When it crumbles (When it crumbles) *We will stand tall (We will stand tall) *Face it all together *At rock fall *Let the rock fall *We will stand tall *At rock faaall 30b04f63dd36cb299d123cf23b3b25817fc5692a Faq 0 3 1026 968 2014-01-04T14:21:38Z Scooby rex 4486 /* What is forbidden on Board Game Arena? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple account and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had a bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. ea83ef3f991f3e664f77c8065e4eb3e9fc45eaf1 1027 1026 2014-01-04T14:22:20Z Scooby rex 4486 /* What is absolutely forbidden in Board Game Arena? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== Board Game Arena platform has been designed to encourage players to maintain a good behaviour. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had a bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. 642a6f93e07228e0a55c19a3084a2d07d8f425f3 1028 1027 2014-01-04T14:23:36Z Scooby rex 4486 /* What if some player does something wrong? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. 6d2f68407a8ecc16b22184f0a4513f30c364e426 Main game logic: yourgamename.game.php 0 86 1040 946 2014-01-06T08:45:43Z Sourisdudesert 1 wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature is e8c03a720c7bf9dd99f27da4b138df14a86868a0 1041 1040 2014-01-06T08:53:15Z Sourisdudesert 1 /* Player elimination */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states. * Game state actions: the logic to run when entering a new game state. * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. 62154d567a823d8cb941350f88708e148cd49684 1042 1041 2014-01-06T09:00:34Z Sourisdudesert 1 /* File Structure */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods above are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. 145ce8691534997b3b513ef02519689d6e065ee9 Your game state machine: states.inc.php 0 90 1043 804 2014-01-06T09:09:19Z Sourisdudesert 1 /* args */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "args" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> === args === (optional) From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state. Example 1 : for Reversi, the list of possible moves during playerTurn state. Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor. Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them. In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them. Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array. Let's see a complete example using args with « Reversi » game : In states.inc.php, we specify some « args » argument for gamestate « playerTurn » : <pre> 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", <================================== HERE "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), </pre> It corresponds to a « argPlayerTurn » method in our PHP code (reversi.game.php): <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves() ); } </pre> Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn : <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> Note: you can also use values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above). Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn). ==== Private infos in args ==== By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic. This is although possible to specify that some data should be sent to some specific players only: Example 1: send an information to active player(s) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private 'active' => array( // Using "active" keyword inside "_private", you select active player(s) 'somePrivateData' => self::getSomePrivateData() // will be send only to active player(s) ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> Example 2: send an information to a specific player (<specific_player_id>) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private <specific_player_id> => array( // you select one specific player with its id 'somePrivateData' => self::getSomePrivateData() // will be send only to <specific_player_id> ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> IMPORTANT: in certain situation (ex: multipleactiveplayer game state) these "private data" features can have a big performance impact. Please do not use if not needed. === updateGameProgression === (optional) IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated. At least one of your game state (any of them) must specify updateGameProgression=>true. 662e0aefe4d493cd3263698181e113351d75c6a2 Moderationpolicy 0 123 1044 867 2014-01-06T12:17:50Z Sourisdudesert 1 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: * the player has been reported several times for the same type of case. * the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. * on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators give more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games played. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). === Incomplete reports === Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: explicit sexual content, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (explicit sexual content, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one noticed the username until now, it is probably not inappropriate. |- ! Table description | Inappropriate table description | If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Kingmaking | Kingmaking action during a game | The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it has to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Bug exploit | Exploit a known bug during a game | The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned. | No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done. |- ! Private information | Some player gives some private information during the game | Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong intent to kill the pleasure of the game by giving some private information during the game. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Multiple accounts | A player is using multiple accounts (most of the time: to boost his ELO rank) | The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. It is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP address, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way. | For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games. |- ! Something else | Translation stealing / vandalism | The player is writing inappropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership, | Immediate ban from the website (to avoid vandalism). |- ! Something else | Player is slow to play | Players have the right to think as long as they do not go over their allotted time. If the player is slow on purpose, the good answer is: thumb down. | No penalty |- ! Something else | Player quit the game before the end | In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else. | No penalty |- |} fd3b875814a1865e5ca8f4def483c31d94b46a3b 1045 1044 2014-01-06T12:23:54Z Sourisdudesert 1 /* Penalty grid */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: * the player has been reported several times for the same type of case. * the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. * on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators give more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games played. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). === Incomplete reports === Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: explicit sexual content, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (explicit sexual content, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one noticed the username until now, it is probably not inappropriate. |- ! Table description | Inappropriate table description | If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Kingmaking | Kingmaking action during a game | The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it has to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Bug exploit | Exploit a known bug during a game | The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned. | No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done. |- ! Private information | Some player gives some private information during the game | Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong intent to kill the pleasure of the game by giving some private information during the game. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Multiple accounts | A player is using multiple accounts (most of the time: to boost his ELO rank) | The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. It is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP address, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way. | For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games. |- ! Something else | Spam / advertising / inappropriate links | The player is using BGA for advertising. In particular: links not related to the purpose of the page, advertising for other online boardgaming websites, spam, ... | |- ! Something else | Translation stealing / vandalism | The player is writing inappropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership, | Immediate ban from the website (to avoid vandalism). |- ! Something else | Player is slow to play | Players have the right to think as long as they do not go over their allotted time. If the player is slow on purpose, the good answer is: thumb down. | No penalty |- ! Something else | Player quit the game before the end | In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else. | No penalty |- |} 34ec666062af04c36bf1fccc6cc61e8f415eb55b 1046 1045 2014-01-06T13:24:42Z Sourisdudesert 1 /* About private jokes */ wikitext text/x-wiki == General rules == === Beyond a Reasonable Doubt === In case there is a any possible doubt, a player should be considered not guilty. === Moderators independance === Moderators must not process reports if they know the protagonists (author or targeted player). Playing online with the protagonist does not mean to "know" them. "Know" means: know them personally or playing with them online very regularly. === Appeal === Players has the right to appeal against the moderation decision, by forwarding received moderation email to "contact@boardgamearena.com". They '''MUST''' explain in the email why the moderator did not respect the BGA moderation policy. If the explanation is not convincing, the email will be ignored. If the player is obviously guilty and if the moderation policy hasn't been violated, BGA admins will double the penalties. === Penalty grid === Moderators should respect the penalties grid as much as possible. However, they have the right to adjust the penalty depending on the gravity of the case. The following situation can lead moderators to increase the penalties: * the player has been reported several times for the same type of case. * the player wrong action can be obviously qualified by one or several of the following terms: racism, xenophobia, homophobia, sexism, and as a rule of thumb any type of discrimination against a particular category of people. * on case there is a provocation, the penalty may be be reduced a little, and the author of the provocation may have a warning BUT, as everyone should keep quiet and polite even if there are provoked, this is a moderator choice. === Relapse === In case there is a relapse, the penalty increases exponentially. This is the moderator job to determine the right penalty to apply in this case, considering the fact that the player has been warned by a first penalty. Moderators should consider there is a relapse only if the new wrong action occurs AFTER the previous penalty has been applied and the associated moderation email has been sent. Considering it's a lot of work to analyze reports about players who do the same action again and again, the "ban forever" penalty can be applied to any case if the player relapses. === Special urgency ban procedure === Whatever the case type, moderators has the right to ban a player from the website (forever) if this player set up a situation that is out of control and must be stopped within hours. This special procedure should only be used if there is an immediate danger for the community (ex: vandalism, flow of insults, massive spam, ...). === About private jokes === If a wrong action happened in a private circle (ex: at a game table, with no spectators), and if none of the present players reported the action, the moderator must consider this was a "private joke" and must not apply any penalty. In the contrary, if the wrong action is public (ex: post/comment on the wall), the moderator may consider this as a wrong action even if there is no report. Note: in case a moderator discovers that this is obviously not a private joke and that something must be reported, the moderator is allowed to create a report for the case. However, in this case, this moderator is not allowed to judge the report. === Prescription === For operational reason, a report that is older than 2 weeks may be closed by moderators because it is too old. === Player profile influence === The player profile IS taken into account to determine if the player is guilty or not guilty. Moderators give more credit to players with a good profile than the other. The player profile is NOT taken into account when choosing the penalty if the player is found guilty. Good profile elements are: * A good thumb up / thumb down ratio. * Player is registered since a long time / has a lot of games played. * Players is involved in the website (ex: realized translations). * Player is supporting BGA (member of the club). === Incomplete reports === Analyzing reports takes a lot of time, and many reports are received. If any needed information is missing in the report, moderators may (and most of the time, should) close the report. == Penalty grid == {| class="wikitable alternance centre" |+ Titre |- ! scope="col" | Category ! scope="col" | Case type ! scope="col" | Details ! scope="col" | Standard penalty |- ! Insults | Insults during a game, on table chat | Must be present in the report: table ID, and the insults terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on general chat | Must be present in the report: the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 30 days for small insults and insanity, Devilkin forever for real insults. In any case: the player should be warn that this is the last warning before ban. |- ! Insults | Insults on public space (wall, forum, comments...) | Must be present in the report: where to find the insult, the insult terms. If the insult is not in English, or if the insult is not obvious, the report author must specify why this is insulting. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Aggressive attitude | Aggressive attitude during a game: can't wait the other player, provocation, ... | As a rule of thumb: as long as there is no insult, this is not an issue: thumb down are the solution. BUT, if the player is really borderline and should be warned, a moderation action is needed. | -1 to -10 reputation penalty. Moderators should explain that this is a small warning, and that a change of attitude is needed. |- ! Avatar | Inappropriate avatar: explicit sexual content, extreme violence, advertising... | If needed, report author should explain why this is inappropriate. Avatar is really inappropriate in 3 cases: 1°) It can hurt underage players (explicit sexual content, extreme violence) 2°) This is advertisement / this violate some intellectual property 3°) The avatar contains a reference that discriminate a group of people (ex: nazi cross) | Avatar immediate removal + Devilkin 3 days to devilkin forever depending on the gravity. In any case: the player should be warn that this is the last warning before ban. If the player obviously don't measure the meaning of the avatar, the penalty can be reduced. |- ! Avatar | Inappropriate username | If needed, report author should explain why this is inappropriate. Username are inappropriate when this is obviously an insult for many people. Moderators shouldn't moderate a username that is insulting by accident in a language that is not widely used on BGA. | Ban from the website. Moderators should explain that the player is welcome with another username on BGA. Note that if the player has a long seniority on BGA (=many games played), moderators should be very cautious on the case: if no one noticed the username until now, it is probably not inappropriate. |- ! Table description | Inappropriate table description | If needed, report author should explain why this is inappropriate. Table description is inappropriate when it contains insults, insanity, or tend to discriminate a group of people. | Devilkin 3 days for small insults and insanity, Devilkin 30 days for real insults. Smaller penalty (ex: 1 day) can be applied if this was obviously a stupid joke. In any case: the player should be warn that this is the last warning before ban. |- ! Kingmaking | Kingmaking action during a game | The report must contains the table id, the exact move number, and the exact explanation why this is a kingmaking action. To declare a player guilty, the player must have played an obvious move against his own interest, and it has to be a good player (clues: his ELO, number of game played, ...). As the difference between a mistake and a kingmaking action is very tight, one kingmaking report is not enough to find a player guilty: only players who regularly play against their interest should be found guilty. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Bug exploit | Exploit a known bug during a game | The bug must have been reported in the forum, and an exact reference to this bug must be in the report, with the table id and the move number. Minor bugs that can be considered as "variants" are NOT concerned (ex: pick 4 cards instead of 3). Bugs that violate the spirit of the game are concerned. | No penalty applies: if there is a bug that has been widely used for a game, a global ELO reset (or an ELO adjustment for players who exploited the bug) will be done. |- ! Private information | Some player gives some private information during the game | Players have the right to pretend things during a game. As these infos could be true or false, and could be exploited by other players too, moderators should be cautious when judging these cases. This case concerns players that had a strong intent to kill the pleasure of the game by giving some private information during the game. | -1 to -10 reputation penalty. Moderators should warn the player that this is a only small warning. Relapses can lead to higher reputation points penalties. |- ! Multiple accounts | A player is using multiple accounts (most of the time: to boost his ELO rank) | The report must contains the usernames of all intimidated accounts, and the reason why the report author think that multiple accounts are used. It is very difficult to find out if different accounts corresponds to different person. For example: BGA accepts that multiple players plays from the same IP address, to allow people from the same family to play at the same table. In addition, some players are using multiple accounts, but these accounts are not playing together (which is acceptable). Strong tools are available for moderators to detect multiple accounts that are used the wrong way. | For secondary accounts: ban forever. For main account: ELO reseted to 1500 / ELO penalty for all games. |- ! Something else | Spam / advertising / inappropriate links | The player is using BGA for advertising. In particular: links not related to the purpose of the page, advertising for other online boardgaming websites, spam, ... | |- ! Something else | Translation stealing / vandalism | The player is writing inappropriate / poor quality translations (or writes a lot of very minor modifications to someone else translation) to gain free club membership, | Immediate ban from the website (to avoid vandalism). |- ! Something else | Player is slow to play | Players have the right to think as long as they do not go over their allotted time. If the player is slow on purpose, the good answer is: thumb down. | No penalty |- ! Something else | Player quit the game before the end | In this case, player automatically gets a ELO penalty + a red mark on his profile. There is no need to do something else. | No penalty |- |} 91f7c78eaee74c38df5fac94a13f00cfe84fbd06 Tutorial reversi 0 57 1047 937 2014-01-09T23:31:57Z Deluxe flame 4630 /* Make the squares appears */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for white and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('img/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "states.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where it is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where it is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in state.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 9c6a8cb2c794566964cbaebf6757a4a8d58e53f8 Grade 0 30 1048 712 2014-01-14T02:59:12Z Tim robinson 4708 /* All grades */ wikitext text/x-wiki Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. == All grades == * '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraphim can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherubim check that Seraphim are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. * '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...) 5953d5338df3e4a588747647198989d0eede4340 Rating 0 16 1049 184 2014-01-15T08:22:08Z Tim robinson 4708 /* Okay, but I want to know the formula ! */ wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game ? == ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples: * If you end the game at a better place than a player with a higher ELO, you gain a lot of points. * If you end the game at a better place than a player with a lower ELO, you gain less points. * If you end the game at a worse place than a player with a lower ELO, you lose a lot points. * And so on... == Some advice == * There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO. * The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win. * The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you lose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent. == How is my ELO ranking computed ? == The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied. ELO system on BGA has some specificity: * During your first 30 games, your ELO rating is more "elastic": you can win (or lose) more points at each game. This way, your ELO rating converge faster to you "natural" rating. * Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you lose a 2-player game against each opponent before you (in game rank). * Games with more than 2 players last longer. For this reason, there's more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula ! == The formula is exactly one's used by the ELO rating system, with the following adjustments: * First of all, if someone left a game for any reason this game is not taken into account by the ELO rating system. * K=60 for the first 30 games, K=40 afterwards. * K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players". * If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600. == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO be3b5bffa0a8ad60134ce93dc6a4f93df0db1ed0 Gamehelptournay 0 143 1050 2014-02-04T15:31:51Z Pikiou 1872 No rules were added, so I took the opportunity to thank Nosnhoj Kräm ^^ wikitext text/x-wiki Thanks to Nosnhoj Kräm (Eeeville) for his Tournay card descriptions used in the BGA adaptation! ab25f7264e6489f116b85b3b93a28bbdc6055ce5 1077 1050 2014-02-20T00:54:42Z Eeeville 1177 wikitext text/x-wiki Thanks to Mark Johnson (Eeeville) for his Tournay card descriptions used in the BGA adaptation! 6087e3fd7a00dd8eab30de396f2d7e435c85a04d 1090 1077 2014-03-08T10:00:53Z Drstuey 3099 started editing this page - will continue later wikitext text/x-wiki Thanks to Mark Johnson (Eeeville) for his Tournay card descriptions used in the BGA adaptation! The '''game ends''' when both of the following conditions are met, or if condition 1 is met by more than one player: # a player has filled 9 spaces with at least 2 visible prestige buildings. # one Town Crier card more than the number of players has been revealed. The last round is triggered at the beginning of the start player's turn and each player gets a normal turn in this round. Then all players can choose a final card to play into their districts. Important notes: * You cannot score more than 12 victory points from the same prestige building. * If two players build the same prestige buildings there is only a single scoring. 94d79bbb06c68138ff9a1a1099f2978b9c760473 1091 1090 2014-03-09T09:53:41Z Drstuey 3099 details of prestige buildings wikitext text/x-wiki Thanks to Mark Johnson (Eeeville) for his Tournay card descriptions used in the BGA adaptation! The '''game ends''' when both of the following conditions are met, or if condition 1 is met by more than one player: # A player has filled 9 spaces with at least 2 visible prestige buildings. # One Town Crier card more than the number of players has been revealed. The last round is triggered at the beginning of the start player's turn and each player gets a normal turn in this round. Then all players can choose a final card to play into their districts. Important notes: * You cannot score more than 12 victory points from the same prestige building. * If two players build the same prestige building there is only a single scoring. ===Details of prestige buildings=== '''Yellow:''' *'''Belfry''': per set (1 yellow + 1 white + 1 red) of buildings or characters *'''City Hall''': per yellow citizen (2x) *'''Cloth Hall''': per yellow building or character (2x) *'''Mint''': per set of 4 deniers (2x) *'''Tour des Six''': per character (2x) '''White:''' *'''Cathedral''': only the player who builds it earns 8 PPs. *'''La Madeleine''': per prestige building (2x) *'''Saint-Brice''': per set (1 yellow + 1 white + 1 red) of buildings or characters *'''Saint-Jacques''': per white building or character (2x) *'''Saint-Nicolas''': per set of citizens you own (1 yellow +1 white +1 red) *'''Saint-Quentin''': per white citizen (2x) '''Red:''' *'''Pont des Trous''': per set (1 yellow + 1 white + 1 red) of citizens *'''Porte de la Vigne''': per red citizen (2x) *'''Tour d’Arras''': per white and yellow building (2x) *'''Tour Henry VIII''': per rampart built (2x) *'''Tour Saint-Georges''': per red card building or character (2x) aba76f1199acfd1fafbb145b912989a43e9bcb0c Restr:BGA transparent horizontal logo.png 6 144 1051 2014-02-12T20:06:45Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:BGA transparent horizontal white logo.png 6 145 1052 2014-02-12T20:09:09Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:BGA transparent vertical logo.png 6 146 1053 2014-02-12T20:10:18Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Logos 0 147 1054 2014-02-12T20:10:37Z Sourisdudesert 1 Created page with "On this page you can find brand assets for Board Game Arena. Please use "right click + save image as" to download needed images. == BGA transparent horizontal logo == (sho..." wikitext text/x-wiki On this page you can find brand assets for Board Game Arena. Please use "right click + save image as" to download needed images. == BGA transparent horizontal logo == (should be used on a white background): [[File:BGA transparent horizontal logo.png]] == BGA transparent horizontal white logo == (should be used on a black background): [[File:BGA transparent horizontal white logo.png]] == BGA transparent vertical logo == [[File:BGA_transparent_vertical_logo.png]] b7180517559277c310a87e737ff30450271c7977 1055 1054 2014-02-12T20:11:10Z Sourisdudesert 1 wikitext text/x-wiki On this page you can find brand assets for Board Game Arena and easy way to create links to BGA. Please use "right click + save image as" to download needed images. == BGA transparent horizontal logo == (should be used on a white background): [[File:BGA transparent horizontal logo.png]] == BGA transparent horizontal white logo == (should be used on a black background): [[File:BGA transparent horizontal white logo.png]] == BGA transparent vertical logo == [[File:BGA_transparent_vertical_logo.png]] e03e41f9b20d1d450803ebf772d56f59f8ddf39f 1060 1055 2014-02-12T20:13:07Z Sourisdudesert 1 wikitext text/x-wiki On this page you can find brand assets for Board Game Arena and easy way to create links to BGA. Please use "right click + save image as" to download needed images. == BGA transparent horizontal logo == (should be used on a white background): [[File:BGA transparent horizontal logo.png]] == BGA transparent horizontal white logo == (should be used on a black background): [[File:BGA transparent horizontal white logo.png]] == BGA transparent vertical logo == [[File:BGA_transparent_vertical_logo.png]] == BGA icon == 16x16: [[File:BGA logo 16.png]] 75x75: [[File:BGA logo 75.png]] 128x128: [[File:BGA logo 512.png]] 512x512: [[File:BGA logo 512.png]] 3c03e32262b480d49428c87ea5980a08ec25b20d 1061 1060 2014-02-12T20:13:24Z Sourisdudesert 1 /* BGA icon */ wikitext text/x-wiki On this page you can find brand assets for Board Game Arena and easy way to create links to BGA. Please use "right click + save image as" to download needed images. == BGA transparent horizontal logo == (should be used on a white background): [[File:BGA transparent horizontal logo.png]] == BGA transparent horizontal white logo == (should be used on a black background): [[File:BGA transparent horizontal white logo.png]] == BGA transparent vertical logo == [[File:BGA_transparent_vertical_logo.png]] == BGA icon == 16x16: [[File:BGA logo 16.png]] 75x75: [[File:BGA logo 75.png]] 128x128: [[File:BGA logo 128.png]] 512x512: [[File:BGA logo 512.png]] a1c641bd1ba13393eec05921f99ef308d7218ec8 1071 1061 2014-02-12T21:05:52Z Sourisdudesert 1 wikitext text/x-wiki On this page you can find brand assets for Board Game Arena and easy way to create links to BGA. Please use "right click + save image as" to download needed images. = BGA buttons = You can use buttons below as links to BGA website: == English == [[File:play_games_online_en.png]] == French == [[File:play_games_online_fr.png]] == German == [[File:play_games_online_de.png]] == Spanish == [[File:play_games_online_es.png]] == Italian == [[File:play_games_online_it.png]] == Chinese (traditional) == [[File:play_games_online_zh.png]] == Chinese (simplified) == [[File:play_games_online_zh_cn.png]] == Japanese == [[File:play_games_online_ja.png]] = BGA logos = == BGA transparent horizontal logo == (should be used on a white background): [[File:BGA transparent horizontal logo.png]] == BGA transparent horizontal white logo == (should be used on a black background): [[File:BGA transparent horizontal white logo.png]] == BGA transparent vertical logo == [[File:BGA_transparent_vertical_logo.png]] == BGA icon == 16x16: [[File:BGA logo 16.png]] 75x75: [[File:BGA logo 75.png]] 128x128: [[File:BGA logo 128.png]] 512x512: [[File:BGA logo 512.png]] 3006bfb0c058b927e3507b2334b8c0f832dfd092 1074 1071 2014-02-12T21:08:32Z Sourisdudesert 1 /* English */ wikitext text/x-wiki On this page you can find brand assets for Board Game Arena and easy way to create links to BGA. Please use "right click + save image as" to download needed images. = BGA buttons = You can use buttons below as links to BGA website: == Language independent == [[File:bga_button.png]] == English == Generic: [[File:play_games_online_en.png]] Play it online: [[File:play_it_on_bga_en.png]] == French == [[File:play_games_online_fr.png]] == German == [[File:play_games_online_de.png]] == Spanish == [[File:play_games_online_es.png]] == Italian == [[File:play_games_online_it.png]] == Chinese (traditional) == [[File:play_games_online_zh.png]] == Chinese (simplified) == [[File:play_games_online_zh_cn.png]] == Japanese == [[File:play_games_online_ja.png]] = BGA logos = == BGA transparent horizontal logo == (should be used on a white background): [[File:BGA transparent horizontal logo.png]] == BGA transparent horizontal white logo == (should be used on a black background): [[File:BGA transparent horizontal white logo.png]] == BGA transparent vertical logo == [[File:BGA_transparent_vertical_logo.png]] == BGA icon == 16x16: [[File:BGA logo 16.png]] 75x75: [[File:BGA logo 75.png]] 128x128: [[File:BGA logo 128.png]] 512x512: [[File:BGA logo 512.png]] e72e3c1053edce9fbbcf1c3b2be00fd1d1d94bc5 1075 1074 2014-02-12T21:14:22Z Sourisdudesert 1 /* BGA buttons */ wikitext text/x-wiki On this page you can find brand assets for Board Game Arena and easy way to create links to BGA. Please use "right click + save image as" to download needed images. = BGA buttons = You can use buttons below as links to BGA website. If you need a button that is not on the list please contact us (contact@boardgamearena.com). == Language independent == [[File:bga_button.png]] == English == Generic: [[File:play_games_online_en.png]] Play it online: [[File:play_it_on_bga_en.png]] == French == [[File:play_games_online_fr.png]] == German == [[File:play_games_online_de.png]] == Spanish == [[File:play_games_online_es.png]] == Italian == [[File:play_games_online_it.png]] == Chinese (traditional) == [[File:play_games_online_zh.png]] == Chinese (simplified) == [[File:play_games_online_zh_cn.png]] == Japanese == [[File:play_games_online_ja.png]] = BGA logos = == BGA transparent horizontal logo == (should be used on a white background): [[File:BGA transparent horizontal logo.png]] == BGA transparent horizontal white logo == (should be used on a black background): [[File:BGA transparent horizontal white logo.png]] == BGA transparent vertical logo == [[File:BGA_transparent_vertical_logo.png]] == BGA icon == 16x16: [[File:BGA logo 16.png]] 75x75: [[File:BGA logo 75.png]] 128x128: [[File:BGA logo 128.png]] 512x512: [[File:BGA logo 512.png]] 06b065e7ed8f5184b92d12ca3bc0b6678a1131da Restr:BGA logo 16.png 6 148 1056 2014-02-12T20:11:45Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:BGA logo 75.png 6 149 1057 2014-02-12T20:11:53Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:BGA logo 128.png 6 150 1058 2014-02-12T20:12:01Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:BGA logo 512.png 6 151 1059 2014-02-12T20:12:08Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Play games online de.png 6 152 1062 2014-02-12T21:01:39Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Play games online en.png 6 153 1063 2014-02-12T21:01:50Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Play games online es.png 6 154 1064 2014-02-12T21:02:00Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Play games online fr.png 6 155 1065 2014-02-12T21:02:08Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 1066 1065 2014-02-12T21:02:18Z Sourisdudesert 1 uploaded a new version of &quot;[[File:Play games online fr.png]]&quot; wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Play games online it.png 6 156 1067 2014-02-12T21:02:28Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Play games online ja.png 6 157 1068 2014-02-12T21:02:37Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Play games online zh.png 6 158 1069 2014-02-12T21:02:51Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Play games online zh cn.png 6 159 1070 2014-02-12T21:03:01Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Bga button.png 6 160 1072 2014-02-12T21:06:36Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Restr:Play it on bga en.png 6 161 1073 2014-02-12T21:06:47Z Sourisdudesert 1 wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Stock 0 97 1076 955 2014-02-19T21:10:34Z Pikiou 1872 /* Complete stock component reference */ wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. At first, don't forget to add "ebg/stock" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <==== HERE ], </pre> The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: * type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. * weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted and their order might change randomly at any time). * image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_gamethemeurl+'img/yourimage.png' </pre> * image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method. '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. '''onItemCreate''' Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it. Complete example: <pre> // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item: this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); (...) // And here is our "setupNewCard": setupNewCard: function( card_div, card_type_id, card_id ) { // Add a special tooltip on the card: this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' ); // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type // Add some custom HTML content INSIDE the Stock item: dojo.place( this.format_block( 'jstpl_my_card_content', { .... } ), card_div.id ); } </pre> == Tips when adding/removing items to/from Stock components == The usual way is the following: '''Situation A''': When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from. '''Situation B''': When you add a card to a stock item, and this card is coming from another stock: * on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48". * then, remove the source item with "removeFromStockById". (note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide). '''Situation C''': When you move a card from a stock item to something that is not a stock item: * insert the card as a classic HTML template (dojo.place / this.format_block). * place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above). * slide it to its new position with "this.slideToObject" * remove the card from the Stock item with "removeFromStockById". Using the methods above, your cards should slided to, from and between your Stock controls smoothly d7f0b2e8d1b241b8e9bd10966b85aa7828974929 1080 1076 2014-02-24T18:05:47Z Een 3 wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. At first, don't forget to add "ebg/stock" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <==== HERE ], </pre> The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: * type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. * weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted and their order might change randomly at any time). * image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_gamethemeurl+'img/yourimage.png' </pre> * image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method. '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. '''onItemCreate''' Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it. Complete example: <pre> // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item: this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); (...) // And here is our "setupNewCard": setupNewCard: function( card_div, card_type_id, card_id ) { // Add a special tooltip on the card: this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' ); // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type // Add some custom HTML content INSIDE the Stock item: dojo.place( this.format_block( 'jstpl_my_card_content', { .... } ), card_div.id ); } </pre> == Tips when adding/removing items to/from Stock components == The usual way is the following: '''Situation A''': When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from. '''Situation B''': When you add a card to a stock item, and this card is coming from another stock: * on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48". * then, remove the source item with "removeFromStockById". (note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide). '''Situation C''': When you move a card from a stock item to something that is not a stock item: * insert the card as a classic HTML template (dojo.place / this.format_block). * place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above). * slide it to its new position with "this.slideToObject" * remove the card from the Stock item with "removeFromStockById". Using the methods above, your cards should slide to, from and between your Stock controls smoothly dae384c29525a1d69dd67e4501a77c283b59a801 1081 1080 2014-02-24T18:22:08Z Een 3 wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. At first, don't forget to add "ebg/stock" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <==== HERE ], </pre> The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "<div>" element (a void <div> element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: * type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. * weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted and their order might change randomly at any time). * image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_gamethemeurl+'img/yourimage.png' </pre> * image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''setSelectionAppeareance( type )''' For each stock control, you can specify a selection highlighting type: * 'border': there will be a red border around selected items (this is the default). The attribute 'apparenceBorderWidth' can be used to manage the width of the border (in pixels). * 'disappear': the selected item will fade out and disappear. This is useful when the selection has the effect of destroying the item. * 'class': there will be an extra 'stockitem_selecte' css class added to the element when it is selected (and removed when unselected). You can override this class in the css file for your game. By default this class definition is: <pre> .stockitem_selected { border: 2px solid red ! important; } </pre> If you want to override it for example to change the border color add this in your <game>.css file: <pre> .stockitem_selected { border: 2px solid orange ! important; } </pre> NB: the 'class' highlighting type has not yet been deployed on the studio - 24/02/2014. This warning will be removed after the next upgrade. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> Note: The "control_name" argument is the ID (the "DOM" id) of the <div> container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method. '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. '''onItemCreate''' Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it. Complete example: <pre> // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item: this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); (...) // And here is our "setupNewCard": setupNewCard: function( card_div, card_type_id, card_id ) { // Add a special tooltip on the card: this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' ); // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type // Add some custom HTML content INSIDE the Stock item: dojo.place( this.format_block( 'jstpl_my_card_content', { .... } ), card_div.id ); } </pre> == Tips when adding/removing items to/from Stock components == The usual way is the following: '''Situation A''': When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from. '''Situation B''': When you add a card to a stock item, and this card is coming from another stock: * on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48". * then, remove the source item with "removeFromStockById". (note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide). '''Situation C''': When you move a card from a stock item to something that is not a stock item: * insert the card as a classic HTML template (dojo.place / this.format_block). * place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above). * slide it to its new position with "this.slideToObject" * remove the card from the Stock item with "removeFromStockById". Using the methods above, your cards should slide to, from and between your Stock controls smoothly 201df1d5f75f0a9223a3d677a435868e6887bef3 1082 1081 2014-02-24T18:33:09Z Een 3 wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. At first, don't forget to add "ebg/stock" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <==== HERE ], </pre> The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "div" element (a void div element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: * type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. * weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted and their order might change randomly at any time). * image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_gamethemeurl+'img/yourimage.png' </pre> * image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''setSelectionAppeareance( type )''' For each stock control, you can specify a selection highlighting type: * 'border': there will be a red border around selected items (this is the default). The attribute 'apparenceBorderWidth' can be used to manage the width of the border (in pixels). * 'disappear': the selected item will fade out and disappear. This is useful when the selection has the effect of destroying the item. * 'class': there will be an extra 'stockitem_selecte' css class added to the element when it is selected (and removed when unselected). You can override this class in the css file for your game. By default this class definition is: <pre> .stockitem_selected { border: 2px solid red ! important; } </pre> If you want to override it for example to change the border color add this in your <game>.css file: <pre> .stockitem_selected { border: 2px solid orange ! important; } </pre> NB: the 'class' highlighting type has not yet been deployed on the studio - 24/02/2014. This warning will be removed after the next upgrade. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> Note: The "control_name" argument is the ID (the "DOM" id) of the "div" container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method. '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. '''onItemCreate''' Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it. Complete example: <pre> // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item: this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); (...) // And here is our "setupNewCard": setupNewCard: function( card_div, card_type_id, card_id ) { // Add a special tooltip on the card: this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' ); // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type // Add some custom HTML content INSIDE the Stock item: dojo.place( this.format_block( 'jstpl_my_card_content', { .... } ), card_div.id ); } </pre> == Tips when adding/removing items to/from Stock components == The usual way is the following: '''Situation A''': When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from. '''Situation B''': When you add a card to a stock item, and this card is coming from another stock: * on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48". * then, remove the source item with "removeFromStockById". (note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide). '''Situation C''': When you move a card from a stock item to something that is not a stock item: * insert the card as a classic HTML template (dojo.place / this.format_block). * place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above). * slide it to its new position with "this.slideToObject" * remove the card from the Stock item with "removeFromStockById". Using the methods above, your cards should slide to, from and between your Stock controls smoothly 9eb6c365aa835914a123b46b22e9f45ccc16c1b9 Faq 0 3 1078 1028 2014-02-22T19:51:24Z Een 3 wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think some player has had bad behavior during a game, you can give him a at the end of the game. If you think some player committed some serious wrongdoing during a game (ex: insult), please report this player to us ("report this player" link from his profile or game result page) so that we can take appropriate measures. a1b0dbea7f9cfbcb77d9cbd8dcf02d3c641cb263 Game interface logic: yourgamename.js 0 88 1079 1009 2014-02-24T17:49:33Z Een 3 /* Scoring dialogs */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ).play(); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> You can also use three extra attributes in the parameter array for the notification: <pre> $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table, "header" => '<div>Some header</div>', "footer" => '<div>Some footer</div>', "closelabel" => clienttranslate( "Closing button label" ) ) ); </pre> *'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors) *'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names) *'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update. == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Reversi example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. '''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 2a4582a2f5ebf347239e3414d23aaa78dee2bff1 1097 1079 2014-03-19T10:51:16Z Sourisdudesert 1 /* Animations */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> You can also use three extra attributes in the parameter array for the notification: <pre> $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table, "header" => '<div>Some header</div>', "footer" => '<div>Some footer</div>', "closelabel" => clienttranslate( "Closing button label" ) ) ); </pre> *'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors) *'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names) *'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update. == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Reversi example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. '''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> a46f2086bc1c43aacfffaaf05d98154cc9a7954f 1099 1097 2014-03-24T17:43:35Z Sourisdudesert 1 /* Adding stuff to player's panel */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> You can also use three extra attributes in the parameter array for the notification: <pre> $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table, "header" => '<div>Some header</div>', "footer" => '<div>Some footer</div>', "closelabel" => clienttranslate( "Closing button label" ) ) ); </pre> *'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors) *'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names) *'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update. == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Gomoku example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. '''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 3edb1b2de886971149bb7afa955790ee664eae63 Grade 0 30 1083 1048 2014-02-28T22:27:16Z Da man 5122 /* All grades */ wikitext text/x-wiki Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. == All grades == * '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraphim can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherubim check that Seraphim are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. * '''Demon''': The grade we give to people when they post things in our forums that we don't really like to hear.. like... how bad administrators we are. Yes, we use censorship... if you don't like we ban you for some days (or forever ...) d61494b57e4426dac356ecc0045b330d4e5ef205 Gamehelppuertorico 0 23 1084 80 2014-03-02T10:26:22Z Een 3 wikitext text/x-wiki == Goal == Be the player with the most victory points at the end of the game by collecting: * victory points earned for buildings * victory point tokens earned at the captain phase * conditional victory points earned at the end of the game for occupied large buildings In case of a tie, the player owning the most doubloons and goods is the winner. == Rules summary == The game is played over several rounds. At the start of a round, the governor selects a role, then each player in turn selects a role. At the end of the round, the governor token moves to the next player. When a role has been chosen, each player in turn plays the action for this role. Only the player who selected the role can use the role privilege. Available roles are the following: * Mayor: colonists set foot in the new world ! Privilege : the mayor can get one more colonist from the supply. Action : in turn, begining with the mayor, players get one colonist from the ship, until it is empty. Then players have to set colonists on their buildings and plantations. * Craftsman: goods are produced. Privilege : the craftsman can produce one more good of his choice. Action : produce goods for your occupied buildings and plantations. * Trader: goods are sold to the trading house. Privilege : the trader earns 1 extra doubloon if he sells. Action : sell one good the trading house doesn't have yet. * Settler : plantations settlement. Privilege : the settler can get a quarry instead of a plantation. Action : get a plantation chosen among those available. * Builder : buildings are bought and built. Privilege : the builder can get a building for 1 doubloon less than the regular price. Action : get a building chosen among those available. * Captain : victory points are won by shipping goods to the old world. Privilege : the captain earns one extra victory points if he ships some goods. Action : select a type of good to load on a cargo ship; 1 victory point is earned for each barrel of this type of good loaded on the ship. * Prospector : gold rush brings money ! Privilege : the prospector gets one doubloon from the bank. Action : none. Please also note that occupied violet buildings have modifier effects for role actions. End of game happens at the end of the round for which one of the following events comes to pass : * there is not enough colonists in the supply to refill the colonist ship at the end of the mayor phase * the last victory point token has been earned during the captain phase * at least one of the players built on his 12th and last free space in the city. == Playing online == Choosing a role : click on the role of your choice in the list on the right of your game board. * Mayor role : accept or refuse to get an extra colonist from the supply. Colonists are then automatically recruited by players. Click on a building or a plantation to setup a colonist on it. Click on a colonist to send it back to San Juan (the counter for colonists in San Juan is situated in your player panel on the right of the page). * Craftsman role : goods production is automated (counters for goods owned are in the player panel on the right of the page). Then, choose one extra good that you can produce as your privilege. * Trader role : choose a good that you want to sell by clicking on the appropriate counter in your player panel. * Settler role : click on the plantation (or quarry) that you want. Placement on your board is automated. * Builder role : click on the building that you want to buy. Placement on your board is automated. * Captain role : click on the cargo boat on which you want to ship some goods. Then choose the type of good that you want to ship by clicking on the appropriate counter in your player panel. At the end of the captain phase, if you have some goods to store (warehouse or windrose), click on the corresponding counter. Stored goods will be highlighted by a red frame. * Prospector role : doubloon is earned immediately. Tooltips are available to give information on roles and buildings by hovering over game elements with the mouse. == 'Balanced game' variant == This variant implements two game balance fixes giving each player an equal chance of winning as listed in the [http://en.wikipedia.org/wiki/Puerto_Rico_%28board_game%29 Puerto Rico (board game) Wikipedia page]. * The prices of the Factory and University buildings are swapped so that the Factory costs 8 doubloons and the University costs 7 doubloons * Any player that starts with a corn plantation starts with 1 doubloon less than the players that start with an indigo plantation. == Two players variant == Craftsman Angst : if this variant is selected, players alternate selecting a role as usual, until the Governor has selected three roles and the opponent has selected two (instead of three in a classic two players game), then the governor token goes to the opponent and a new round starts. So it avoids the consecutive selection of two roles by the same player that happens on a change of round with the classic two player game. This variant is described on [http://www.boardgamegeek.com/thread/679955/the-craftsman-angst-variant-the-most-popular-revis Board Game Geek]. '''Have a good game !''' 4af14d346dd971fe509fdbba835b794d1148c492 1085 1084 2014-03-02T10:27:41Z Een 3 /* Two players variant */ wikitext text/x-wiki == Goal == Be the player with the most victory points at the end of the game by collecting: * victory points earned for buildings * victory point tokens earned at the captain phase * conditional victory points earned at the end of the game for occupied large buildings In case of a tie, the player owning the most doubloons and goods is the winner. == Rules summary == The game is played over several rounds. At the start of a round, the governor selects a role, then each player in turn selects a role. At the end of the round, the governor token moves to the next player. When a role has been chosen, each player in turn plays the action for this role. Only the player who selected the role can use the role privilege. Available roles are the following: * Mayor: colonists set foot in the new world ! Privilege : the mayor can get one more colonist from the supply. Action : in turn, begining with the mayor, players get one colonist from the ship, until it is empty. Then players have to set colonists on their buildings and plantations. * Craftsman: goods are produced. Privilege : the craftsman can produce one more good of his choice. Action : produce goods for your occupied buildings and plantations. * Trader: goods are sold to the trading house. Privilege : the trader earns 1 extra doubloon if he sells. Action : sell one good the trading house doesn't have yet. * Settler : plantations settlement. Privilege : the settler can get a quarry instead of a plantation. Action : get a plantation chosen among those available. * Builder : buildings are bought and built. Privilege : the builder can get a building for 1 doubloon less than the regular price. Action : get a building chosen among those available. * Captain : victory points are won by shipping goods to the old world. Privilege : the captain earns one extra victory points if he ships some goods. Action : select a type of good to load on a cargo ship; 1 victory point is earned for each barrel of this type of good loaded on the ship. * Prospector : gold rush brings money ! Privilege : the prospector gets one doubloon from the bank. Action : none. Please also note that occupied violet buildings have modifier effects for role actions. End of game happens at the end of the round for which one of the following events comes to pass : * there is not enough colonists in the supply to refill the colonist ship at the end of the mayor phase * the last victory point token has been earned during the captain phase * at least one of the players built on his 12th and last free space in the city. == Playing online == Choosing a role : click on the role of your choice in the list on the right of your game board. * Mayor role : accept or refuse to get an extra colonist from the supply. Colonists are then automatically recruited by players. Click on a building or a plantation to setup a colonist on it. Click on a colonist to send it back to San Juan (the counter for colonists in San Juan is situated in your player panel on the right of the page). * Craftsman role : goods production is automated (counters for goods owned are in the player panel on the right of the page). Then, choose one extra good that you can produce as your privilege. * Trader role : choose a good that you want to sell by clicking on the appropriate counter in your player panel. * Settler role : click on the plantation (or quarry) that you want. Placement on your board is automated. * Builder role : click on the building that you want to buy. Placement on your board is automated. * Captain role : click on the cargo boat on which you want to ship some goods. Then choose the type of good that you want to ship by clicking on the appropriate counter in your player panel. At the end of the captain phase, if you have some goods to store (warehouse or windrose), click on the corresponding counter. Stored goods will be highlighted by a red frame. * Prospector role : doubloon is earned immediately. Tooltips are available to give information on roles and buildings by hovering over game elements with the mouse. == 'Balanced game' variant == This variant implements two game balance fixes giving each player an equal chance of winning as listed in the [http://en.wikipedia.org/wiki/Puerto_Rico_%28board_game%29 Puerto Rico (board game) Wikipedia page]. * The prices of the Factory and University buildings are swapped so that the Factory costs 8 doubloons and the University costs 7 doubloons * Any player that starts with a corn plantation starts with 1 doubloon less than the players that start with an indigo plantation. == Two players variant == Craftsman Angst : if this variant is selected, players alternate selecting a role as usual, until the Governor has selected '''three''' roles and the opponent has selected '''two''' roles (instead of three in a classic two players game), then the governor token goes to the opponent and a new round starts. This variant avoids the consecutive selection of two roles by the same player which happens on a change of round with the classic two player game rules. This variant is described on [http://www.boardgamegeek.com/thread/679955/the-craftsman-angst-variant-the-most-popular-revis Board Game Geek]. '''Have a good game !''' 2d7aca9b12d032b70bc405a63a994ec943d7f481 Gamehelptokaido 0 134 1086 998 2014-03-03T00:10:48Z Sumner 5143 /* End of the journey */ wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible. To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== '''Farm''' : The player earns 3 coins. '''Hot Spring''' : The player takes a Hot Spring card. These cards are worth 2 or 3 points. '''Temple''' : The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. '''Encounters''' : The player draws one Encounter card and receives a bonus: :* Shokunin - one Souvenir :* Annaibito - one Panorama :* Samurai - 3 points :* Kuge - 3 coins :* Miko - 1 point and 1 coin to the Temple (from the bank) '''Village''' : The player draws 3 Souvenir cards and can purchase one or more of these cards. : Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks. : Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection. : As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type. :* The first Souvenir in a set is worth 1 point. :* The second Souvenir in a set is worth 3 points. :* The third Souvenir in a set is worth 5 points. :* The fourth Souvenir in a set is worth 7 points. '''Panorama''' : Panoramas are made of 3, 4 or 5 sections. : When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ». : Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card. : '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy). '''Inns''' : All Travelers must stop at each Inn. : The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points. : The first traveler occupies the space nearest the road, and later travelers form a line after him. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. : He can then purchase one Meal card of his choice by paying its price. : He adds this card, face up, to his collection and places the remaining cards next to the board, face down. : He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards. : '''IMPORTANT:''' :* A traveler cannot taste the same culinary specialty twice during his journey. :* A traveler can never purchase more than one Meal card per Inn. :* A traveler is never obliged to purchase a Meal card. == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf 6d73c686ae25a635291489a1902f4e9b3d406184 1087 1086 2014-03-03T07:13:23Z Sumner 5143 /* Expansions */ wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible. To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== '''Farm''' : The player earns 3 coins. '''Hot Spring''' : The player takes a Hot Spring card. These cards are worth 2 or 3 points. '''Temple''' : The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. '''Encounters''' : The player draws one Encounter card and receives a bonus: :* Shokunin - one Souvenir :* Annaibito - one Panorama :* Samurai - 3 points :* Kuge - 3 coins :* Miko - 1 point and 1 coin to the Temple (from the bank) '''Village''' : The player draws 3 Souvenir cards and can purchase one or more of these cards. : Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks. : Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection. : As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type. :* The first Souvenir in a set is worth 1 point. :* The second Souvenir in a set is worth 3 points. :* The third Souvenir in a set is worth 5 points. :* The fourth Souvenir in a set is worth 7 points. '''Panorama''' : Panoramas are made of 3, 4 or 5 sections. : When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ». : Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card. : '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy). '''Inns''' : All Travelers must stop at each Inn. : The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points. : The first traveler occupies the space nearest the road, and later travelers form a line after him. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. : He can then purchase one Meal card of his choice by paying its price. : He adds this card, face up, to his collection and places the remaining cards next to the board, face down. : He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards. : '''IMPORTANT:''' :* A traveler cannot taste the same culinary specialty twice during his journey. :* A traveler can never purchase more than one Meal card per Inn. :* A traveler is never obliged to purchase a Meal card. == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf == The New Encounters == This expansion adds 4 new Encounter cards. Details here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large 7b1a4cb6dc6d2bbfafc545d8a32aff644af2f7ef 1088 1087 2014-03-03T07:20:31Z Sumner 5143 /* The New Encounters */ wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible. To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== '''Farm''' : The player earns 3 coins. '''Hot Spring''' : The player takes a Hot Spring card. These cards are worth 2 or 3 points. '''Temple''' : The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. '''Encounters''' : The player draws one Encounter card and receives a bonus: :* Shokunin - one Souvenir :* Annaibito - one Panorama :* Samurai - 3 points :* Kuge - 3 coins :* Miko - 1 point and 1 coin to the Temple (from the bank) '''Village''' : The player draws 3 Souvenir cards and can purchase one or more of these cards. : Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks. : Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection. : As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type. :* The first Souvenir in a set is worth 1 point. :* The second Souvenir in a set is worth 3 points. :* The third Souvenir in a set is worth 5 points. :* The fourth Souvenir in a set is worth 7 points. '''Panorama''' : Panoramas are made of 3, 4 or 5 sections. : When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ». : Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card. : '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy). '''Inns''' : All Travelers must stop at each Inn. : The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points. : The first traveler occupies the space nearest the road, and later travelers form a line after him. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. : He can then purchase one Meal card of his choice by paying its price. : He adds this card, face up, to his collection and places the remaining cards next to the board, face down. : He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards. : '''IMPORTANT:''' :* A traveler cannot taste the same culinary specialty twice during his journey. :* A traveler can never purchase more than one Meal card per Inn. :* A traveler is never obliged to purchase a Meal card. == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf == The New Encounters == This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large 830cea6507fbd647bbb61b278a115936ee4fbd2a 1089 1088 2014-03-03T07:26:23Z Sumner 5143 /* Cross Roads Expansion */ wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible. To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== '''Farm''' : The player earns 3 coins. '''Hot Spring''' : The player takes a Hot Spring card. These cards are worth 2 or 3 points. '''Temple''' : The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. '''Encounters''' : The player draws one Encounter card and receives a bonus: :* Shokunin - one Souvenir :* Annaibito - one Panorama :* Samurai - 3 points :* Kuge - 3 coins :* Miko - 1 point and 1 coin to the Temple (from the bank) '''Village''' : The player draws 3 Souvenir cards and can purchase one or more of these cards. : Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks. : Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection. : As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type. :* The first Souvenir in a set is worth 1 point. :* The second Souvenir in a set is worth 3 points. :* The third Souvenir in a set is worth 5 points. :* The fourth Souvenir in a set is worth 7 points. '''Panorama''' : Panoramas are made of 3, 4 or 5 sections. : When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ». : Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card. : '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy). '''Inns''' : All Travelers must stop at each Inn. : The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points. : The first traveler occupies the space nearest the road, and later travelers form a line after him. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. : He can then purchase one Meal card of his choice by paying its price. : He adds this card, face up, to his collection and places the remaining cards next to the board, face down. : He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards. : '''IMPORTANT:''' :* A traveler cannot taste the same culinary specialty twice during his journey. :* A traveler can never purchase more than one Meal card per Inn. :* A traveler is never obliged to purchase a Meal card. == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added. Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf == The New Encounters == This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large 7b8a2e7ec0781136dbefc471f49d6c37bdf99f67 1093 1089 2014-03-15T06:26:38Z Diversionarchitect 5221 /* Cross Roads Expansion */ wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible. To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== '''Farm''' : The player earns 3 coins. '''Hot Spring''' : The player takes a Hot Spring card. These cards are worth 2 or 3 points. '''Temple''' : The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. '''Encounters''' : The player draws one Encounter card and receives a bonus: :* Shokunin - one Souvenir :* Annaibito - one Panorama :* Samurai - 3 points :* Kuge - 3 coins :* Miko - 1 point and 1 coin to the Temple (from the bank) '''Village''' : The player draws 3 Souvenir cards and can purchase one or more of these cards. : Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks. : Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection. : As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type. :* The first Souvenir in a set is worth 1 point. :* The second Souvenir in a set is worth 3 points. :* The third Souvenir in a set is worth 5 points. :* The fourth Souvenir in a set is worth 7 points. '''Panorama''' : Panoramas are made of 3, 4 or 5 sections. : When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ». : Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card. : '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy). '''Inns''' : All Travelers must stop at each Inn. : The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points. : The first traveler occupies the space nearest the road, and later travelers form a line after him. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. : He can then purchase one Meal card of his choice by paying its price. : He adds this card, face up, to his collection and places the remaining cards next to the board, face down. : He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards. : '''IMPORTANT:''' :* A traveler cannot taste the same culinary specialty twice during his journey. :* A traveler can never purchase more than one Meal card per Inn. :* A traveler is never obliged to purchase a Meal card. == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added. Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf Note: The faces for the fortune die (gambling at the farm) has the faces: x0,x1,x2,x3,x3,x4 == The New Encounters == This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large 0bddf507512bf0e338c2781499f2463416bbf225 1094 1093 2014-03-15T06:27:28Z Diversionarchitect 5221 /* Cross Roads Expansion */ wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible. To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== '''Farm''' : The player earns 3 coins. '''Hot Spring''' : The player takes a Hot Spring card. These cards are worth 2 or 3 points. '''Temple''' : The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. '''Encounters''' : The player draws one Encounter card and receives a bonus: :* Shokunin - one Souvenir :* Annaibito - one Panorama :* Samurai - 3 points :* Kuge - 3 coins :* Miko - 1 point and 1 coin to the Temple (from the bank) '''Village''' : The player draws 3 Souvenir cards and can purchase one or more of these cards. : Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks. : Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection. : As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type. :* The first Souvenir in a set is worth 1 point. :* The second Souvenir in a set is worth 3 points. :* The third Souvenir in a set is worth 5 points. :* The fourth Souvenir in a set is worth 7 points. '''Panorama''' : Panoramas are made of 3, 4 or 5 sections. : When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ». : Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card. : '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy). '''Inns''' : All Travelers must stop at each Inn. : The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points. : The first traveler occupies the space nearest the road, and later travelers form a line after him. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. : He can then purchase one Meal card of his choice by paying its price. : He adds this card, face up, to his collection and places the remaining cards next to the board, face down. : He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards. : '''IMPORTANT:''' :* A traveler cannot taste the same culinary specialty twice during his journey. :* A traveler can never purchase more than one Meal card per Inn. :* A traveler is never obliged to purchase a Meal card. == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added. Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf Note: The faces for the Fortune die (for gambling at the farm) has these faces: x0,x1,x2,x3,x3,x4 == The New Encounters == This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large 1d23a61bd5a434ef3902015e87c1783b487f2f36 1095 1094 2014-03-15T06:27:48Z Diversionarchitect 5221 /* Cross Roads Expansion */ wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible. To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== '''Farm''' : The player earns 3 coins. '''Hot Spring''' : The player takes a Hot Spring card. These cards are worth 2 or 3 points. '''Temple''' : The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. '''Encounters''' : The player draws one Encounter card and receives a bonus: :* Shokunin - one Souvenir :* Annaibito - one Panorama :* Samurai - 3 points :* Kuge - 3 coins :* Miko - 1 point and 1 coin to the Temple (from the bank) '''Village''' : The player draws 3 Souvenir cards and can purchase one or more of these cards. : Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks. : Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection. : As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type. :* The first Souvenir in a set is worth 1 point. :* The second Souvenir in a set is worth 3 points. :* The third Souvenir in a set is worth 5 points. :* The fourth Souvenir in a set is worth 7 points. '''Panorama''' : Panoramas are made of 3, 4 or 5 sections. : When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ». : Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card. : '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy). '''Inns''' : All Travelers must stop at each Inn. : The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points. : The first traveler occupies the space nearest the road, and later travelers form a line after him. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. : He can then purchase one Meal card of his choice by paying its price. : He adds this card, face up, to his collection and places the remaining cards next to the board, face down. : He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards. : '''IMPORTANT:''' :* A traveler cannot taste the same culinary specialty twice during his journey. :* A traveler can never purchase more than one Meal card per Inn. :* A traveler is never obliged to purchase a Meal card. == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added. Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf Note: The Fortune die (for gambling at the farm) has these faces: x0,x1,x2,x3,x3,x4 == The New Encounters == This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large 886bfc75a19df7fd10826b09f158d27524676626 1096 1095 2014-03-15T06:28:05Z Diversionarchitect 5221 /* Cross Roads Expansion */ wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible. To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== '''Farm''' : The player earns 3 coins. '''Hot Spring''' : The player takes a Hot Spring card. These cards are worth 2 or 3 points. '''Temple''' : The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. '''Encounters''' : The player draws one Encounter card and receives a bonus: :* Shokunin - one Souvenir :* Annaibito - one Panorama :* Samurai - 3 points :* Kuge - 3 coins :* Miko - 1 point and 1 coin to the Temple (from the bank) '''Village''' : The player draws 3 Souvenir cards and can purchase one or more of these cards. : Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks. : Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection. : As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type. :* The first Souvenir in a set is worth 1 point. :* The second Souvenir in a set is worth 3 points. :* The third Souvenir in a set is worth 5 points. :* The fourth Souvenir in a set is worth 7 points. '''Panorama''' : Panoramas are made of 3, 4 or 5 sections. : When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ». : Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card. : '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy). '''Inns''' : All Travelers must stop at each Inn. : The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points. : The first traveler occupies the space nearest the road, and later travelers form a line after him. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. : He can then purchase one Meal card of his choice by paying its price. : He adds this card, face up, to his collection and places the remaining cards next to the board, face down. : He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards. : '''IMPORTANT:''' :* A traveler cannot taste the same culinary specialty twice during his journey. :* A traveler can never purchase more than one Meal card per Inn. :* A traveler is never obliged to purchase a Meal card. == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added. Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf Note: The Fortune die (for gambling at the farm) has these faces: x0, x1, x2, x3, x3, x4 == The New Encounters == This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large 1c97478bd1c3715be28d901489239d5133e5bc2a Gamehelptroyes 0 26 1092 708 2014-03-14T22:38:05Z Drstuey 3099 + add the different levels of scoring for the characters wikitext text/x-wiki == Goal == Be the player with the most victory points at the end of the game. == Rules summary == (This rules summary is based on the game help written by [http://boardgamegeek.com/user/pregremlin Andrew Agard] for Board Game Geek, under Creative Commons license. Please see [http://boardgamegeek.com/filepage/66976/complete-rules-reference-1-page-fold-in-half original file] here for details. Thank you Andrew !) ===Initial Placement=== * In clockwise order place a citizen in empty space of one building * Continue in counter clockwise order from last player and so on until all citizens placed ===Game play=== ====Phase 0: Reveal the Activity cards==== Reveal activity card for each color corresponding to current round (first 3 rounds only) ====Phase 1: Income and salaries==== Receive 10 deniers and pay 1 per Bishopric and 2 per Palace citizen or lose 2 VP ====Phase 2: Assembling the workforce==== Roll yellow/white/red die per citizen in City Hall/Bishopric/Palace and place in district ====Phase 3: Events==== Reveal top red and white or yellow Event and place to right of queue (unlimited Events) Events take effect from left to right * Military: start player takes 1 black die per die symbol * Other events: see annex (can’t execute: execute as much as possible and lose 2 VP) After Events, roll black dice and counter: * Start player must counter highest-value with one or more dice form district. Total value must be >= die. Discard dice. May counter several dice at once * Gain 1 influence per dice countered (can’t counter: discard die and lose 2 VP) * In order players must counter highest remaining until all countered * Use any color dice. Double red dice. Can’t buy dice or use activity cubes ====Phase 4: Actions==== See below. ====Phase 5: End of the round==== Receive deniers from district Return citizens lying on buildings to personal supplies Return unused dice to general supply Pass start player card left. ===Actions=== In order each player can use 1-3 matching dice for one action or pass. Round ends when no dice available or all players have passed May pay player or bank (gray) to use dice. If using 1/2/3 dice pay 2/4/6 deniers per dice ====Activate Activity Card==== Must have tradesman. Hire if necessary by paying indicated amount in deniers. Place citizen on free space (or illustration if full) from personal supply or any board location * 1 tradesman per player per card * Must activate at least once if tradesman hired * Citizens on card cannot be moved to newly freed space Immediate effect: activation cost (round down) determines color and use of dice Delayed effect: place cubes equal to activation cost. Use later (one cube per action) ====Construct Cathedral==== * Use 1-3 white dice to place 1-3 cubes on same-numbered construction site * Must place on lower levels before placing in higher levels for each set of valued spaces * Gain 1 VP and 1 or 2 Influence for each cube placed in spaces 1-3 or 4-6 ====Combat Events==== * Activation cost (round down) defines dice and number of cubes to place on card * Place cubes on small banner starting with upper left. Gain 1 influence for each. Only place on a single card each action and can’t place more cubes than banners Event countered when banners filled * Most cubes earns higher reward (tied: total rounded down, 2nd earns nothing). If only 1 player on card earn both rewards. * 2nd most cubes earns smaller reward (tied: total rounded down) * Most cubes takes card (tied: player who placed first). Discard if neutral has most * Marauding: rewards given, cubes removed, and then event is available again ====Place a citizen on building==== * Use exactly one die to place one citizen from personal supply or any board location on first space of matching building row or space corresponding to die color and value * Shift existing citizens to right. Citizens pushed off are laid on building illustration * If already have expelled citizen nobody can expel your citizens from that building ====Use Agriculture==== * Gain number of deniers equal to total value divided by 2 (round down) ===Pass=== * If dice still in any city square, pass and receive 2 deniers which are placed in district * Each turn add another denier to district ==Characters scoring== ===Chretien de Troyes=== Awards citizens placed on the 3 principal buildings * 1 VP for 3+ (4+ with 2 players) * 3 VP for 5+ (6+ with 2 players) * 6 VP for 7+ (8+ with 2 players) ===Urbain IV=== Awards cubes placed on the cathedral * 1 VP for 3+ (4+ with 2 players) * 3 VP for 5+ (6+ with 2 players) * 6 VP for 7+ (8+ with 2 players) ===Thibaut II=== Awards deniers * 1 VP for 6+ * 3 VP for 12+ * 6 VP for 18+ ===Hugues de Payns=== Awards influence * 1 VP for 5+ * 3 VP for 10+ * 6 VP for 15+ ===Le Florentin=== Awards tradesman on the activity cards * 1 VP for 2+ * 3 VP for 4+ * 6 VP for 6+ ===Henry I=== Awards event cards * 1 VP for 1+ * 3 VP for 3+ * 6 VP for 5+ e000835f92220c6f16d0a1a52e246e365c2f0017 Gamehelptzolkin 0 129 1098 978 2014-03-23T02:55:55Z Sumner 5143 /* For Each Round */ wikitext text/x-wiki Rules are here: http://czechgames.com/files/Tzolkin_EN.pdf == '''For Each Round''' == - Each player takes their turn, going around the table - On a food day, feed your workers and take your rewards - Advance the Calendar == '''Player turn''' == - '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple) - '''Either place workers OR pick up workers''' -- ''Placing workers'': pay for the number of workers you place plus the cost noted next to each placed workers -- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either --- Use the action where your worker was standing --- Use a lower action on the wheel from where your worker was standing(if not standing on a free action space,pay 1 corn for each step back) --- Do nothing. == '''Food Day''' == -'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for. -- For each worker not fed, you lose 3 points -'''Take Rewards''' --''Middle of Age (Brown days)'' --- Receive items shown on the left edge of temples from step you are on and all steps below -- ''End of Age (Teal Days)'' --- Remove all Age 1 buildings and fill spaces with Age 2 buildings/ --- Receive points shown on the right edge of temples for the step you are on. --- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus. == '''Advance the Calendar''' == If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day. Otherwise: - The worker on the Starting Player space returns to the player -- If this person was not the starting player, they take the starting player marker. -- If they were the starting player, the starting player marker is moved to the player on his left - Advance the Tzolk'in Gear one day. - The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears. -- If you use this option, flip your board to dark side up. -- This does not avoid food days. df8f36fa1da14ce79c2df6f252a145990f5f28d2 Gamehelpkalah 0 162 1100 2014-04-08T09:29:08Z Stst 2180 Created page with "===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called kalah. A player owns the six holes cl..." wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called kalah. A player owns the six holes closest to him and the kalah on his right side. Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. ===OBJECT=== The object of the game is to capture more stones than one's opponent. ===RULES=== At the beginning of the game, from 3 to 6 stones are placed in each hole. Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has captured most stones is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== "Pie rule" - Second player can take opponent's first move and change side of the board. "Empty Capture" - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' de34e78cae9854089d843dd9b32e6e461460ee89 1101 1100 2014-04-09T06:46:15Z Stst 2180 wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah. A player owns the six holes closest to him and the Kalah on his right side. Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. ===OBJECT=== The object of the game is to capture more stones than one's opponent. ===RULES=== At the beginning of the game, from 3 to 6 stones are placed in each hole. Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has collected most stones in his/her Kalah is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== "Pie rule" - Second player can take opponent's first move and change side of the board. "Empty Capture" - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' dd278ce076daa8be794993744bdaaebc59f8a14a 1102 1101 2014-04-10T04:26:55Z Stst 2180 /* RULES */ wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah. A player owns the six holes closest to him and the Kalah on his right side. Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. ===OBJECT=== The object of the game is to capture more stones than one's opponent. ===RULES=== At the beginning of the game, from 3 to 6 stones are placed in each hole. Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has collected most stones in his/her Kalah is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== "Pie rule" - Second player can take opponent's first move and change side of the board. "Empty Capture" - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' 8beba5bfc392f48ad6ec7a1b1646ae5833f1172a 1103 1102 2014-04-10T04:27:44Z Stst 2180 /* RULES */ wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah. A player owns the six holes closest to him and the Kalah on his right side. Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. ===OBJECT=== The object of the game is to capture more stones than one's opponent. ===RULES=== At the beginning of the game, from 3 to 6 stones are placed in each hole. Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has collected most stones in his/her Kalah is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== "Pie rule" - Second player can take opponent's first move and change side of the board. "Empty Capture" - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' dd278ce076daa8be794993744bdaaebc59f8a14a 1104 1103 2014-04-10T07:48:00Z Stst 2180 wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah. A player owns the six holes closest to him and the Kalah on his right side. Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. ===OBJECT=== The object of the game is to capture more stones than one's opponent. ===RULES=== At the beginning of the game, from 3 to 6 stones are placed in each hole. Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has collected most stones in his/her Kalah is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== "Pie rule" - Second player can take opponent's first move and change side of the board. "Empty Capture" - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' 8beba5bfc392f48ad6ec7a1b1646ae5833f1172a 1105 1104 2014-04-10T09:40:17Z Stst 2180 /* VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME) */ wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah. A player owns the six holes closest to him and the Kalah on his right side. Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. ===OBJECT=== The object of the game is to capture more stones than one's opponent. ===RULES=== At the beginning of the game, from 3 to 6 stones are placed in each hole. Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has collected most stones in his/her Kalah is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== «Pie rule» - Second player can take opponent's first move and change side of the board. «Empty Capture» - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' 4fe7f391761f5d53938f87ca7d6a78c95d1acc89 1112 1105 2014-04-28T20:02:18Z Stst 2180 /* VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME) */ wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah. A player owns the six holes closest to him and the Kalah on his right side. Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. ===OBJECT=== The object of the game is to capture more stones than one's opponent. ===RULES=== At the beginning of the game, from 3 to 6 stones are placed in each hole. Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has collected most stones in his/her Kalah is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== «Pie rule» - Second player can take opponent's first move and change sides of the board. «Empty Capture» - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' 2f516a35fa025af19ded3b509148e680b150ee45 Steps to create a BGA game 0 117 1106 957 2014-04-19T21:57:26Z Adam badura 5433 Missing character added wikitext text/x-wiki Here's a summary of the different steps you would follow when developing a game with BGA Studio. {| class="wikitable" |- ! Step !! How to reach this ste?p !! What happened during the step? |- | Initial || [[How to join BGA developer team?]] || You can choose to join an existing team / create a new project |- | Assigned || You choosed a game || You can start the development of the game |- | Pre-alpha || You've started to write some piece of code || You develop the game. During this phase, we can assist you with the framework and give you some pieces of advice. |- | Alpha || You tell us that your development is finished || "BGA review": we are reviewing your game and check if it respects [http://fr.slideshare.net/boardgamearena/bga-studio-guidelines BGA guidelines]. If not, we will ask you (and help you) to fix them. |- | Private beta || We give a "go" || "Publisher review": On preproduction platform, the publisher, the designer, we and you can test the game together and separately. We help you to take into account remarks from the publisher and the designer. |- | Public beta || The adaptation is approved by the publisher || We find together a good launch date for the game, we announce the game on BGA news, and then player can start to play! During the first days, it is common that some bugs are reported by players, and you can fix them following the instructions in [[Post-release phase]]. |- | Gold || The game is stable on BGA || Congrats! You can still modify and optimize things following the instructions in [[Post-release phase]]. |} 09800b383fedaa37ef8609c93cd105d61a633472 Gamehelplibertalia 0 105 1107 756 2014-04-24T15:09:05Z Lowre 5460 /* How to Play */ Come giocare wikitext text/x-wiki Libertalia is an amazing and original card game. During three campaigns, you have to gather doubloons and booty tiles to become the wealthiest pirate. Each turn, you play one card to try to be the first to choose which share of the booty will be yours. Of course, each card has special powers that completely break this "routine". One thing that makes Libertalia original is that everyone starts with the same set of cards. That's why you'll have to choose carefully which moment to play each card, and to try to read your opponents' strategies. == '''How to Play''' == The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases: Phase 1: Sunrise Phase 2: Day Phase 3: Dusk Phase 4: Night''' In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons. '''''Phase 1: Sunrise''''' In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right. '''''Phase 2: Day''''' The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first). '''''Phase 3: Dusk''''' Each crew must claim a booty token from below the ship. Tokens are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed. '''''Phase 4: Night''''' The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early! Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure. After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns. To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward. Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner. Come giocare Il gioco consiste in tre campagne, suddivise in 6 giorni. Ogni giorno ha 4 fasi : Fase 1 : Sunrise Fase 2 : Day Fase 3 : Dusk Fase 4 : Notte Nella prima campagna , tutti i giocatori hanno un insieme casuale identico di 9 carte di equipaggio e 10 dobloni . Fase 1 : Sunrise In questa fase , ogni giocatore sceglie segretamente una carta equipaggio da giocare . Una volta che tutti sono pronti , i giocatori rivelano i loro membri dell'equipaggio scelti e metterli sulla nave cargo dal basso a sinistra per il più alto sulla destra . Se c'è un pareggio , il numero tie breaker inferiore va sinistra superiore. Durante questa fase , tutte le azioni speciali che si svolgono durante l'alba capita da sinistra a destra . Fase 2 : Giornata L'unica cosa che accade in questa fase è tutti i membri dell'equipaggio ad azione giorno devono prendere , in ordine crescente di rango . (più basso va prima) . Fase 3 : Dusk Ogni equipaggio deve richiedere un token bottino da sotto la nave . I token sono scelti in ordine di rango ( l'opposto di Fase 2) diminuendo così l'equipaggio più alto rango ottenere la migliore selezione dei gettoni . Dopo un equipaggio rivendica un bottino e si risolve con la loro azione crepuscolo ( se presenti ) siano immediatamente messi in tana del loro giocatore prima della prossima bottino è affermato ( che è importante se qualcuno sta sostenendo una sciabola in seguito . ) In alcuni casi ci potrebbe essere più bottino di rivendicare quando il turno di un equipaggio di credito viene risolto il che significa che non ottengono bottino e andare al loro covo a mani vuote . Fase 4 : Notte L'unica cosa che accade in questa fase è membri dell'equipaggio usano le loro azioni notturne . La differenza è tutti i membri dell'equipaggio nella tua tana risolvere le loro azioni notturne ogni notte . In modo che Barkeep ( la sua azione è di segnare voi 1 doblone ogni notte ) si gioca il giorno 1 della campagna in corso , vi terrà pagare ogni notte ( finché egli rimane in vita . ) Giocare le carte la sera presto ! Nota : Tutto l'equipaggio deve risolvere il più delle loro azioni possibili, anche se sfavorevole a se stessi o il loro controllo ! Il Brute potrebbe uccidere se stesso , il Cannoneer deve pagare 3 oro , anche se non ci sono equipaggi ammissibili in una tana per uccidere , il commerciante venderà il set di gioielli o mappe del tesoro se non si hanno altre serie di tesori di corrispondenza. Dopo il 6 ° giorno della campagna , il round è finito . I giocatori risolvono tutti " fine della campagna" azioni dei membri dell'equipaggio ancora vivo nelle loro tane (sì , i membri dell'equipaggio possono essere uccisi ) . Tutti i membri dell'equipaggio utilizzati vengono rimossi dal gioco . Ogni giocatore somma il valore dei loro gettoni bottino e dobloni ( restituirli alla banca ) e sposta il proprio segnalino punteggio più avanti sulla pista . Ogni giocatore deve avere tre carte rimaste in mano . Questi riporto nei prossimi 2 campagne . Per impostazione per la prossima campagna ogni giocatore riceve 10 nuovi dobloni e aggiungere un insieme casuale identico di 6 carte equipaggio a tre membri dell'equipaggio rimasto . Così i giocatori possono avere una mano leggermente diversi l'uno dall'altro andando avanti . Turni 2 e 3 il gioco proprio come turno 1 . Alla fine della partita il giocatore con il maggior numero di punti vittoria è il vincitore . c133f13c9b4c50f66a04f77499b6535010ffac1d 1108 1107 2014-04-24T15:10:39Z Lowre 5460 wikitext text/x-wiki Libertalia is an amazing and original card game. During three campaigns, you have to gather doubloons and booty tiles to become the wealthiest pirate. Each turn, you play one card to try to be the first to choose which share of the booty will be yours. Of course, each card has special powers that completely break this "routine". One thing that makes Libertalia original is that everyone starts with the same set of cards. That's why you'll have to choose carefully which moment to play each card, and to try to read your opponents' strategies. == '''How to Play''' == The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases: Phase 1: Sunrise Phase 2: Day Phase 3: Dusk Phase 4: Night''' In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons. '''''Phase 1: Sunrise''''' In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right. '''''Phase 2: Day''''' The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first). '''''Phase 3: Dusk''''' Each crew must claim a booty token from below the ship. Tokens are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed. '''''Phase 4: Night''''' The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early! Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure. After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns. To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward. Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner. '''Come giocare''' Il gioco consiste in tre campagne, suddivise in 6 giorni. Ogni giorno ha 4 fasi : Fase 1 : Sunrise Fase 2 : Day Fase 3 : Dusk Fase 4 : Notte Nella prima campagna , tutti i giocatori hanno un insieme casuale identico di 9 carte di equipaggio e 10 dobloni . Fase 1 : Sunrise In questa fase , ogni giocatore sceglie segretamente una carta equipaggio da giocare . Una volta che tutti sono pronti , i giocatori rivelano i loro membri dell'equipaggio scelti e metterli sulla nave cargo dal basso a sinistra per il più alto sulla destra . Se c'è un pareggio , il numero tie breaker inferiore va sinistra superiore. Durante questa fase , tutte le azioni speciali che si svolgono durante l'alba capita da sinistra a destra . Fase 2 : Giornata L'unica cosa che accade in questa fase è tutti i membri dell'equipaggio ad azione giorno devono prendere , in ordine crescente di rango . (più basso va prima) . Fase 3 : Dusk Ogni equipaggio deve richiedere un token bottino da sotto la nave . I token sono scelti in ordine di rango ( l'opposto di Fase 2) diminuendo così l'equipaggio più alto rango ottenere la migliore selezione dei gettoni . Dopo un equipaggio rivendica un bottino e si risolve con la loro azione crepuscolo ( se presenti ) siano immediatamente messi in tana del loro giocatore prima della prossima bottino è affermato ( che è importante se qualcuno sta sostenendo una sciabola in seguito . ) In alcuni casi ci potrebbe essere più bottino di rivendicare quando il turno di un equipaggio di credito viene risolto il che significa che non ottengono bottino e andare al loro covo a mani vuote . Fase 4 : Notte L'unica cosa che accade in questa fase è membri dell'equipaggio usano le loro azioni notturne . La differenza è tutti i membri dell'equipaggio nella tua tana risolvere le loro azioni notturne ogni notte . In modo che Barkeep ( la sua azione è di segnare voi 1 doblone ogni notte ) si gioca il giorno 1 della campagna in corso , vi terrà pagare ogni notte ( finché egli rimane in vita . ) Giocare le carte la sera presto ! Nota : Tutto l'equipaggio deve risolvere il più delle loro azioni possibili, anche se sfavorevole a se stessi o il loro controllo ! Il Brute potrebbe uccidere se stesso , il Cannoneer deve pagare 3 oro , anche se non ci sono equipaggi ammissibili in una tana per uccidere , il commerciante venderà il set di gioielli o mappe del tesoro se non si hanno altre serie di tesori di corrispondenza. Dopo il 6 ° giorno della campagna , il round è finito . I giocatori risolvono tutti " fine della campagna" azioni dei membri dell'equipaggio ancora vivo nelle loro tane (sì , i membri dell'equipaggio possono essere uccisi ) . Tutti i membri dell'equipaggio utilizzati vengono rimossi dal gioco . Ogni giocatore somma il valore dei loro gettoni bottino e dobloni ( restituirli alla banca ) e sposta il proprio segnalino punteggio più avanti sulla pista . Ogni giocatore deve avere tre carte rimaste in mano . Questi riporto nei prossimi 2 campagne . Per impostazione per la prossima campagna ogni giocatore riceve 10 nuovi dobloni e aggiungere un insieme casuale identico di 6 carte equipaggio a tre membri dell'equipaggio rimasto . Così i giocatori possono avere una mano leggermente diversi l'uno dall'altro andando avanti . Turni 2 e 3 il gioco proprio come turno 1 . Alla fine della partita il giocatore con il maggior numero di punti vittoria è il vincitore . f4df15211fe2334967c8177c2019865512b8e6b5 1109 1108 2014-04-24T15:15:28Z Lowre 5460 wikitext text/x-wiki Libertalia is an amazing and original card game. During three campaigns, you have to gather doubloons and booty tiles to become the wealthiest pirate. Each turn, you play one card to try to be the first to choose which share of the booty will be yours. Of course, each card has special powers that completely break this "routine". One thing that makes Libertalia original is that everyone starts with the same set of cards. That's why you'll have to choose carefully which moment to play each card, and to try to read your opponents' strategies. == '''How to Play''' == The game consists of 3 campaigns, broken up into 6 days. '''Each day has 4 phases: Phase 1: Sunrise Phase 2: Day Phase 3: Dusk Phase 4: Night''' In the first campaign, all players have an identical random set of 9 crew cards and 10 doubloons. '''''Phase 1: Sunrise''''' In this phase, each player secretly chooses one crew card to play. Once everyone is ready, the players reveal their chosen crew members and place them on the cargo ship from lowest on the left to the highest on the right. If there is a tie, the lower tie breaker number goes the left of the higher. During this phase, all special actions that take place during sunrise happen from left to right. '''''Phase 2: Day''''' The only thing that happens in this phase is all crew members with a day action must take it, in increasing order of rank. (lowest goes first). '''''Phase 3: Dusk''''' Each crew must claim a booty token from below the ship. Tokens are chosen in decreasing order of rank (the opposite of Phase 2) so the highest ranking crew get the best selection of tokens. After a crew claims a booty and resolves their dusk action (if any) they are immediately placed in their player's den before the next booty is claimed (which is important if someone is claiming a sabre later.) In some circumstances there might be no more booty to claim when a crew's turn to claim is resolved which means they get no booty and go to their den empty handed. '''''Phase 4: Night''''' The only thing that happens in this phase is crew members use their Night actions. The difference is all crew members in your den resolve their night actions every night. So that Barkeep (his action is to score you 1 doubloon each night) you played on day 1 of the current campaign, will keep paying you every night (as long as he stays alive.) Play those night cards early! Note: All crew must resolve as much of their actions as possible, even if disadvantageous to themselves or their controller! The Brute might kill himself, the Cannoneer has to pay 3 gold even if there are no eligible crew in a den to kill, the Merchant will sell your set of jewels or treasure maps if you have no other sets of matching treasure. After the 6th day of the campaign, the round is over. Players resolve all “end of campaign” actions of crew members still alive in their dens (yes, crew members can be killed). All used crew members are removed from the game. Each player adds up the value of their booty tokens and doubloons (returning them to the bank) and moves their score marker ahead on the track. Each player should have 3 cards left in their hand. These carry over into the next 2 campaigns. To setup for the next campaign each player gets 10 new doubloons and add an identical random set of 6 crew cards to the three crew left over. Thus players may have a slightly different hand from each other going forward. Rounds 2 and 3 play just like round 1. At the end of the game the player with the most victory points is the winner. 1db47195e1202cd4d33fe0ee8d989c0b20b42c52 Gamehelpeightmastersrevenge 0 163 1110 2014-04-26T01:07:10Z Jinnh 4158 Created page with "Overview and aim of the game 8 Masters’ Revenge is a fighting game for 1 to 4 players (only available for 2 players on BGA). You are a martial arts master and you want to ..." wikitext text/x-wiki Overview and aim of the game 8 Masters’ Revenge is a fighting game for 1 to 4 players (only available for 2 players on BGA). You are a martial arts master and you want to beat your opponents, strike after strike. Your only weapons are your 2 hands, represented by the 2 cards you have in play. Find the weak point in your opponent’s guard to deal damage to him. As soon as his ‘’health‘’ marker reaches the last space of his life track (whose length depends of the number of players), he is out of the game. The last surviving player wins the fight. d22dc9606ab12588626e4484a0a5d397f5804020 1111 1110 2014-04-26T01:15:45Z Jinnh 4158 wikitext text/x-wiki Overview and aim of the game 8 Masters’ Revenge is a fighting game for 1 to 4 players (only available for 2 players on BGA). You are a martial arts master and you want to beat your opponents, strike after strike. Your only weapons are your 2 hands, represented by the 2 cards you have in play. Find the weak point in your opponent’s guard to deal damage to him. As soon as his "health" marker reaches the last space of his life track (whose length depends of the number of players), he is out of the game. The last surviving player wins the fight. a7b9a9eb420c0ef12ced22819d203e4a3fded472 1138 1111 2014-06-06T09:05:16Z Sawyer einherjar 5056 wikitext text/x-wiki ===Overview and aim of the game=== 8 Masters’ Revenge is a fighting game for 1 to 4 players (only available for 2 players on BGA). You are a martial arts master and you want to beat your opponents, strike after strike. Your only weapons are your 2 hands, represented by the 2 cards you have in play. Find the weak point in your opponent’s guard to deal damage to him. As soon as his "health" marker reaches the last space of his life track (whose length depends of the number of players), he is out of the game. The last surviving player wins the fight. ====Turn break down==== =====Active player (attacker)===== The active player can choose to perform one of the following actions: Draw 2 cards (or 1 card if he or she already has 3 cards in hand due to having a handsize limit of 4 cards). After drawing cards the active player may move one token, in his or her area, to an adjacent field. ''Or'' Perform an attack! In order to do so the active player has to place a card from his/her hand in play. This card has to be put adjacent to the two cards already in play. The card that is not adjacent to the new card will be discarded and is the card that performs the attack. Now 5 steps take place: # Apply token effect (if any). # Check if the attack hits! An attack hits if the ''attacker’s attack value'' is '''exactly equal''' to the ''defender’s defense value''. (the attack value is the value created with the new card put in play; more below). # Deal damage if the attack hits. # Apply the effect of the discarded card. # Play an extra turn if a pair was formed with the new card (meaning that the center numbers are equal -> 1/1 2/2 3/3 4/4 5/5). During the extra turn a new attack can be launched or '''1''' card can be drawn. When no new pair is formed or when a card is drawn the turn is passed on the the second player. =====Passive player (defender)===== When the active player lauches an attack, the passive player has 3 options if certain conditions are met. <ol> <li>Do nothing and take the blow (shouting: "''that doesn't hurt me!''") <li>Block the attack. You can block an attack if you meet the following condition. <ol><li>If you have a card in play that has the same color as the card with which is attacked. (so you can block a yellow card with a yellow card). </li></ol> Blocking will reduce incoming dmg with 1. However, a card used for blocking stays in its blocking state, until it is discarded (used to attack), meaning you cannot use it a second time for blocking and you cannot form a pair with it. Most important if you're attacked a second time with a card of the same color and you still have the card in the blocking area '''you will suffer 2 additional damage'''.</li> <li>Counter the attack. You can launch a counter attack on your opponents attack when you meet 2 conditions. <ol><li> you have in play a card with a dragon symbol</li> <li>you have a card in your hand with a dragon symbol</li></ol> If both conditions are met, you can form a dragon pair by playing the dragon card from your hand next to the dragon card you have in play. Be careful, as your opponent may perform a counter attack on your counter attack, if your opponent matches both conditions as well. When the attacker is not able to counter the counter attack his/her turn ends immediately and as such the effects from the card with which was attacked are not applied. (You can continue countering each other until one of you no longer has a card with a dragon symbol, to put in play). </li> </ol> =====Computation of defense and attack values===== The Attack value is equal to the sum of the numbers in the center of the couple of cards you have in play<br/> The Defense value is equal to the sum of the numbers of both ends of the couple of cards you have in play Example: you have a 2-4 and a 5-1 card in play. (2-4/5-1)<br/> Thus attack value = 9 (4+5)<br/> and defense value = 3 (2+1) de4f65abbf17dc50f2429a6e2d4f27eff4c8619b 1140 1138 2014-06-10T14:09:58Z Steel breeze 2275 Correction: lauches --> launches wikitext text/x-wiki ===Overview and aim of the game=== 8 Masters’ Revenge is a fighting game for 1 to 4 players (only available for 2 players on BGA). You are a martial arts master and you want to beat your opponents, strike after strike. Your only weapons are your 2 hands, represented by the 2 cards you have in play. Find the weak point in your opponent’s guard to deal damage to him. As soon as his "health" marker reaches the last space of his life track (whose length depends of the number of players), he is out of the game. The last surviving player wins the fight. ====Turn break down==== =====Active player (attacker)===== The active player can choose to perform one of the following actions: Draw 2 cards (or 1 card if he or she already has 3 cards in hand due to having a handsize limit of 4 cards). After drawing cards the active player may move one token, in his or her area, to an adjacent field. ''Or'' Perform an attack! In order to do so the active player has to place a card from his/her hand in play. This card has to be put adjacent to the two cards already in play. The card that is not adjacent to the new card will be discarded and is the card that performs the attack. Now 5 steps take place: # Apply token effect (if any). # Check if the attack hits! An attack hits if the ''attacker’s attack value'' is '''exactly equal''' to the ''defender’s defense value''. (the attack value is the value created with the new card put in play; more below). # Deal damage if the attack hits. # Apply the effect of the discarded card. # Play an extra turn if a pair was formed with the new card (meaning that the center numbers are equal -> 1/1 2/2 3/3 4/4 5/5). During the extra turn a new attack can be launched or '''1''' card can be drawn. When no new pair is formed or when a card is drawn the turn is passed on the the second player. =====Passive player (defender)===== When the active player launches an attack, the passive player has 3 options if certain conditions are met. <ol> <li>Do nothing and take the blow (shouting: "''that doesn't hurt me!''") <li>Block the attack. You can block an attack if you meet the following condition. <ol><li>If you have a card in play that has the same color as the card with which is attacked. (so you can block a yellow card with a yellow card). </li></ol> Blocking will reduce incoming dmg with 1. However, a card used for blocking stays in its blocking state, until it is discarded (used to attack), meaning you cannot use it a second time for blocking and you cannot form a pair with it. Most important if you're attacked a second time with a card of the same color and you still have the card in the blocking area '''you will suffer 2 additional damage'''.</li> <li>Counter the attack. You can launch a counter attack on your opponents attack when you meet 2 conditions. <ol><li> you have in play a card with a dragon symbol</li> <li>you have a card in your hand with a dragon symbol</li></ol> If both conditions are met, you can form a dragon pair by playing the dragon card from your hand next to the dragon card you have in play. Be careful, as your opponent may perform a counter attack on your counter attack, if your opponent matches both conditions as well. When the attacker is not able to counter the counter attack his/her turn ends immediately and as such the effects from the card with which was attacked are not applied. (You can continue countering each other until one of you no longer has a card with a dragon symbol, to put in play). </li> </ol> =====Computation of defense and attack values===== The Attack value is equal to the sum of the numbers in the center of the couple of cards you have in play<br/> The Defense value is equal to the sum of the numbers of both ends of the couple of cards you have in play Example: you have a 2-4 and a 5-1 card in play. (2-4/5-1)<br/> Thus attack value = 9 (4+5)<br/> and defense value = 3 (2+1) f77073d1d422c88d34737f08329bb389b20227fd 1143 1140 2014-06-11T13:56:39Z Sawyer einherjar 5056 wikitext text/x-wiki ===Overview and aim of the game=== 8 Masters’ Revenge is a fighting game for 1 to 4 players (only available for 2 players on BGA). You are a martial arts master and you want to beat your opponents, strike after strike. Your only weapons are your 2 hands, represented by the 2 cards you have in play. Find the weak point in your opponent’s guard to deal damage to him. As soon as his "health" marker reaches the last space of his life track (whose length depends of the number of players), he is out of the game. The last surviving player wins the fight. ====Turn break down==== =====Active player (attacker)===== The active player can choose to perform one of the following actions: Draw 2 cards (or 1 card if he or she already has 3 cards in hand due to having a handsize limit of 4 cards). After drawing cards the active player may move one token, in his or her area, to an adjacent field. '''Important: A damange token that lies on a emtpy field can only be placed on an adjacent empty field, and a damage token that lies on a card can only be placed on an adjacent card!''' ''Or'' Perform an attack! In order to do so the active player has to place a card from his/her hand in play. This card has to be put adjacent to the two cards already in play. The card that is not adjacent to the new card will be discarded and is the card that performs the attack. Now 5 steps take place: # Apply token effect (if any). # Check if the attack hits! An attack hits if the ''attacker’s attack value'' is '''exactly equal''' to the ''defender’s defense value''. (the attack value is the value created with the new card put in play; more below). # Deal damage if the attack hits. # Apply the effect of the discarded card. # Play an extra turn if a pair was formed with the new card (meaning that the center numbers are equal -> 1/1 2/2 3/3 4/4 5/5). During the extra turn a new attack can be launched or '''1''' card can be drawn. When no new pair is formed or when a card is drawn the turn is passed on the the second player. =====Passive player (defender)===== When the active player launches an attack, the passive player has 3 options if certain conditions are met. <ol> <li>Do nothing and take the blow (shouting: "''that doesn't hurt me!''") <li>Block the attack. You can block an attack if you meet the following condition. <ol><li>If you have a card in play that has the same color as the card with which is attacked. (so you can block a yellow card with a yellow card). </li></ol> Blocking will reduce incoming dmg with 1. However, a card used for blocking stays in its blocking state, until it is discarded (used to attack), meaning you cannot use it a second time for blocking and you cannot form a pair with it. Most important if you're attacked a second time with a card of the same color and you still have the card in the blocking area '''you will suffer 2 additional damage'''.</li> <li>Counter the attack. You can launch a counter attack on your opponents attack when you meet 2 conditions. <ol><li> you have in play a card with a dragon symbol</li> <li>you have a card in your hand with a dragon symbol</li></ol> If both conditions are met, you can form a dragon pair by playing the dragon card from your hand next to the dragon card you have in play. Be careful, as your opponent may perform a counter attack on your counter attack, if your opponent matches both conditions as well. When the attacker is not able to counter the counter attack his/her turn ends immediately and as such the effects from the card with which was attacked are not applied. (You can continue countering each other until one of you no longer has a card with a dragon symbol, to put in play). </li> </ol> =====Computation of defense and attack values===== The Attack value is equal to the sum of the numbers in the center of the couple of cards you have in play<br/> The Defense value is equal to the sum of the numbers of both ends of the couple of cards you have in play Example: you have a 2-4 and a 5-1 card in play. (2-4/5-1)<br/> Thus attack value = 9 (4+5)<br/> and defense value = 3 (2+1) 04904199800e9d3fc3dc92a8f090f48197975fa7 Stock 0 97 1113 1082 2014-04-30T03:45:33Z Pikiou 1872 /* Complete stock component reference */ wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. At first, don't forget to add "ebg/stock" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <==== HERE ], </pre> The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "div" element (a void div element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: * type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. * weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted and their order might change randomly at any time). * image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_gamethemeurl+'img/yourimage.png' </pre> * image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2: several items can be selected by the player at the same time. '''setSelectionAppearance( type )''' For each stock control, you can specify a selection highlighting type: * 'border': there will be a red border around selected items (this is the default). The attribute 'apparenceBorderWidth' can be used to manage the width of the border (in pixels). * 'disappear': the selected item will fade out and disappear. This is useful when the selection has the effect of destroying the item. * 'class': there will be an extra 'stockitem_selecte' css class added to the element when it is selected (and removed when unselected). You can override this class in the css file for your game. By default this class definition is: <pre> .stockitem_selected { border: 2px solid red ! important; } </pre> If you want to override it for example to change the border color add this in your <game>.css file: <pre> .stockitem_selected { border: 2px solid orange ! important; } </pre> NB: the 'class' highlighting type has not yet been deployed on the studio - 24/02/2014. This warning will be removed after the next upgrade. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> Note: The "control_name" argument is the ID (the "DOM" id) of the "div" container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method. '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. '''onItemCreate''' Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it. Complete example: <pre> // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item: this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); (...) // And here is our "setupNewCard": setupNewCard: function( card_div, card_type_id, card_id ) { // Add a special tooltip on the card: this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' ); // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type // Add some custom HTML content INSIDE the Stock item: dojo.place( this.format_block( 'jstpl_my_card_content', { .... } ), card_div.id ); } </pre> == Tips when adding/removing items to/from Stock components == The usual way is the following: '''Situation A''': When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from. '''Situation B''': When you add a card to a stock item, and this card is coming from another stock: * on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48". * then, remove the source item with "removeFromStockById". (note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide). '''Situation C''': When you move a card from a stock item to something that is not a stock item: * insert the card as a classic HTML template (dojo.place / this.format_block). * place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above). * slide it to its new position with "this.slideToObject" * remove the card from the Stock item with "removeFromStockById". Using the methods above, your cards should slide to, from and between your Stock controls smoothly 2b1ec2b323e69ad70dab9bdbb1cda8408ab3a751 Game interface logic: yourgamename.js 0 88 1114 1099 2014-04-30T23:36:24Z Quinarbre 4507 /* Tooltips */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''this.addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips '''this.removeTooltip( nodeId )''' Remove a tooltip from the DOM node. == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> You can also use three extra attributes in the parameter array for the notification: <pre> $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table, "header" => '<div>Some header</div>', "footer" => '<div>Some footer</div>', "closelabel" => clienttranslate( "Closing button label" ) ) ); </pre> *'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors) *'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names) *'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update. == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Gomoku example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. '''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 4f79eb54f61f8719ada11d802de902007c28bccb 1136 1114 2014-06-05T16:00:00Z Archduke 1630 /* General tips */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; this.isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> Note: the third parameter of dojo.place can take various interesting value: "first", "after", ... [http://dojotoolkit.org/reference-guide/1.7/dojo/place.html See full doc on dojo.place]. Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''this.addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips '''this.removeTooltip( nodeId )''' Remove a tooltip from the DOM node. == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> You can also use three extra attributes in the parameter array for the notification: <pre> $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table, "header" => '<div>Some header</div>', "footer" => '<div>Some footer</div>', "closelabel" => clienttranslate( "Closing button label" ) ) ); </pre> *'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors) *'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names) *'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update. == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Gomoku example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. '''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 85da8a14d1d8814f2f3bc9c3b3cf408ddda4394e Gamehelpyatzy 0 122 1115 891 2014-05-03T18:14:51Z Elizharg 5503 Yahtzee rules wikitext text/x-wiki The game Yahtzee consists of 13 rounds. In each round, you roll 5 dice and then score the roll in a different category of your choice. During a round, you can roll the dice up to three times before scoring -- the initial roll (in which you must roll all the dice), plus two optional re-rolls of any or all dice. There are 13 scoring categories, and each must be used for one of the 13 rounds. This often results in a zero score for some categories. The 13 scoring categories are as follows: 1-6: There is one category for each number on the die. In these categories, the score is the sum of the pips on the dice of that number. For example, a roll of 1-1-2-5-5 could be scored as 2 points in the "ones" category, 2 points in the "twos" category, 10 points in the "fives" category, or 0 points in the "threes," "fours," or "sixes." If a player scores a total of at least 63 points across these six boxes, a bonus of 35 points is added. 7. Three-Of-A-Kind: At least three dice showing the same face -- Points equal the sum of all 5 dice (not just the 3 of a kind) 8. Four-Of-A-Kind: At least four dice showing the same face -- Points equal the sum of all 5 dice (not just the 4 of a kind) 9. Full House: A three-of-a-kind and a pair -- 25 points 10. Small Straight: Four sequential dice 1-2-3-4, 2-3-4-5, or 3-4-5-6) -- 30 points 11. Large Straight: Five sequential dice (1-2-3-4-5 or 2-3-4-5-6) -- 40 points 12. Yahtzee: All five dice showing the same face -- 50 points (plus, once you have scored 50 pts for a Yahtzee, a 2nd Yahtzee gives a bonus of 100 points) 13. Chance: Any combination -- points equal the sum of all 5 dice 776d4c5ac23c727f3c05fed2bb0937dee1bfa822 Multipleaccounts 0 164 1116 2014-05-05T13:58:24Z Sourisdudesert 1 Created page with "Board Game Arena multiple accounts policy == The Main Rule == '''One BGA account = One person''' == Playing from the same IP == This is '''authorized''' to play at the sam..." wikitext text/x-wiki Board Game Arena multiple accounts policy == The Main Rule == '''One BGA account = One person''' == Playing from the same IP == This is '''authorized''' to play at the same table from the same IP (internet address). The warning message "this player plays from the same internet address than another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game. If you want to play from the same internet address than another person: * The best option is not to play at the same table, or play at a table where you know everyone. * If you play with strangers, make them comfortable by the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner, and so on. When some of your opponents are playing from the same IP: * You may refuse (politely) to play with them. * You should probably be vigilant and check that they are not collaborating during the game. * But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report. 11e1220a86f528dfe8a53931e0317e7542087764 1117 1116 2014-05-05T13:58:40Z Sourisdudesert 1 wikitext text/x-wiki == The Main Rule == '''One BGA account = One person''' == Playing from the same IP == This is '''authorized''' to play at the same table from the same IP (internet address). The warning message "this player plays from the same internet address than another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game. If you want to play from the same internet address than another person: * The best option is not to play at the same table, or play at a table where you know everyone. * If you play with strangers, make them comfortable by the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner, and so on. When some of your opponents are playing from the same IP: * You may refuse (politely) to play with them. * You should probably be vigilant and check that they are not collaborating during the game. * But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report. 72a58b9679e610d0e6ba699ae3b49c95dcfa41ea 1118 1117 2014-05-05T14:07:25Z Sourisdudesert 1 wikitext text/x-wiki == The Main Rule == '''One BGA account = One person''' == Playing from the same IP == This is '''authorized''' to play at the same table from the same IP (internet address). The warning message "this player plays from the same internet address than another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game. If you want to play from the same internet address than another person: * The best option is not to play at the same table, or play at a table where you know everyone. * If you play with strangers, make them comfortable by the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner, and so on. When some of your opponents are playing from the same IP: * You may refuse (politely) to play with them. * You should probably be vigilant and check that they are not collaborating during the game. * But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report. == Boosting your ELO by playing against yourself == This is the most stupid and useless thing to do on BGA. Why? Because this is very easy to detect, and because the penalty is: * all your secondary account are removed. * your primary account is reset to 1500 ELO for all games. Why this is so easy to detect: * When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO. * In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game. * In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account". * Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless. If you have a lot of time to spend, please try to get better at this game and please do not try to cheat. 4ca2266ca185fd0f934c9a957c8559f991a14865 1121 1118 2014-05-07T01:08:18Z Wie95 5528 /* The Main Rule */ wikitext text/x-wiki == The Main Rule == '''One BGA account = One person''' == 重點規範 == '''一個 BGA 帳號 = 一個人''' == Playing from the same IP == This is '''authorized''' to play at the same table from the same IP (internet address). The warning message "this player plays from the same internet address than another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game. If you want to play from the same internet address than another person: * The best option is not to play at the same table, or play at a table where you know everyone. * If you play with strangers, make them comfortable by the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner, and so on. When some of your opponents are playing from the same IP: * You may refuse (politely) to play with them. * You should probably be vigilant and check that they are not collaborating during the game. * But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report. == Boosting your ELO by playing against yourself == This is the most stupid and useless thing to do on BGA. Why? Because this is very easy to detect, and because the penalty is: * all your secondary account are removed. * your primary account is reset to 1500 ELO for all games. Why this is so easy to detect: * When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO. * In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game. * In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account". * Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless. If you have a lot of time to spend, please try to get better at this game and please do not try to cheat. 3c0cb8189393503b7d0f4805f764542bc2539627 1123 1121 2014-05-10T23:38:26Z Thanks204 5546 /* The Main Rule */ wikitext text/x-wiki == The Main Rule == '''One BGA account = One person''' == 主要規則 == " 一個BGA帳號 = 一個人 " == 重點規範 == '''一個 BGA 帳號 = 一個人''' == Playing from the same IP == This is '''authorized''' to play at the same table from the same IP (internet address). The warning message "this player plays from the same internet address than another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game. If you want to play from the same internet address than another person: * The best option is not to play at the same table, or play at a table where you know everyone. * If you play with strangers, make them comfortable by the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner, and so on. When some of your opponents are playing from the same IP: * You may refuse (politely) to play with them. * You should probably be vigilant and check that they are not collaborating during the game. * But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report. == Boosting your ELO by playing against yourself == This is the most stupid and useless thing to do on BGA. Why? Because this is very easy to detect, and because the penalty is: * all your secondary account are removed. * your primary account is reset to 1500 ELO for all games. Why this is so easy to detect: * When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO. * In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game. * In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account". * Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless. If you have a lot of time to spend, please try to get better at this game and please do not try to cheat. 9740ac53ced680550fa0e1eed23d1e370a9c16f9 1124 1123 2014-05-10T23:38:42Z Thanks204 5546 /* 重點規範 */ wikitext text/x-wiki == The Main Rule == '''One BGA account = One person''' == 主要規則 == " 一個BGA帳號 = 一個人 " == Playing from the same IP == This is '''authorized''' to play at the same table from the same IP (internet address). The warning message "this player plays from the same internet address than another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game. If you want to play from the same internet address than another person: * The best option is not to play at the same table, or play at a table where you know everyone. * If you play with strangers, make them comfortable by the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner, and so on. When some of your opponents are playing from the same IP: * You may refuse (politely) to play with them. * You should probably be vigilant and check that they are not collaborating during the game. * But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report. == Boosting your ELO by playing against yourself == This is the most stupid and useless thing to do on BGA. Why? Because this is very easy to detect, and because the penalty is: * all your secondary account are removed. * your primary account is reset to 1500 ELO for all games. Why this is so easy to detect: * When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO. * In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game. * In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account". * Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless. If you have a lot of time to spend, please try to get better at this game and please do not try to cheat. 7b8f8300f560377c85a28703261912807614165f 1125 1124 2014-05-12T16:29:11Z Sourisdudesert 1 wikitext text/x-wiki == The Main Rule == '''One BGA account = One person''' == Playing from the same IP == This is '''authorized''' to play at the same table from the same IP (internet address). The warning message "this player plays from the same internet address than another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game. If you want to play from the same internet address than another person: * The best option is not to play at the same table, or play at a table where you know everyone. * If you play with strangers, make them comfortable by the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner, and so on. When some of your opponents are playing from the same IP: * You may refuse (politely) to play with them. * You should probably be vigilant and check that they are not collaborating during the game. * But you don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report. == Boosting your ELO by playing against yourself == This is the most stupid and useless thing to do on BGA. Why? Because this is very easy to detect, and because the penalty is: * all your secondary account are removed. * your primary account is reset to 1500 ELO for all games. Why this is so easy to detect: * When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO. * In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game. * In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account". * Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless. If you have a lot of time to spend, please try to get better at this game and please do not try to cheat. 43b162060f6c49a1b0ccd036ece84d982d717e6f Help 0 4 1119 507 2014-05-06T20:36:10Z Sawyer einherjar 5056 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadöra|Armadöra]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[GamehelpDiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpelfenland|Elfenland]] * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] </td> <td valign="top"> * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[GamehelpHex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpyearofthedragon|In the Year of the Dragon]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] </td> <td valign="top"> * [[Gamehelperudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamgehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelptheboss|The Boss]] </td> <td valign="top"> * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechesnutstablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyahtzee|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] <td> </tr> </table> a07a0b0b1662d8ab90012069265c6495f0a85cfb 1120 1119 2014-05-06T20:46:07Z Sawyer einherjar 5056 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpelfenland|Elfenland]] * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] </td> <td valign="top"> * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] </td> <td valign="top"> * [[Gamehelperudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelptheboss|The Boss]] </td> <td valign="top"> * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] <td> </tr> </table> f5b50ffad8b8b64bbf003e3ded15de14d76aecaf 1122 1120 2014-05-07T09:13:45Z Sawyer einherjar 5056 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpelfenland|Elfenland]] * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] </td> <td valign="top"> * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] </td> <td valign="top"> * [[Gamehelperudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelpsechsnimmt|Take 5!]] </td> <td valign="top"> * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> 211c41f5e679ff3eca9a6be8af58f2330ae8decf 1137 1122 2014-06-06T07:38:30Z Sawyer einherjar 5056 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpeightmastersrevenge|8 Master's revenge]] * [[Gamehelpelfenland|Elfenland]] * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] </td> <td valign="top"> * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] </td> <td valign="top"> * [[Gamehelpniagara|Niagara]] * [[Gamehelperudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] </td> <td valign="top"> * [[Gamehelpsechsnimmt|Take 5!]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> 1871b8ccddd491c0cc0236259ca9ec3ecdcc9e64 1145 1137 2014-06-12T08:51:00Z Sawyer einherjar 5056 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpeightmastersrevenge|8 Master's revenge]] * [[Gamehelpelfenland|Elfenland]] * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] </td> <td valign="top"> * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] </td> <td valign="top"> * [[Gamehelpniagara|Niagara]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] </td> <td valign="top"> * [[Gamehelpsechsnimmt|Take 5!]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> 54728048711eb85a49222ead8edcbac1af09f24d 1148 1145 2014-06-18T08:23:23Z Sawyer einherjar 5056 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpeightmastersrevenge|8 Master's revenge]] * [[Gamehelpelfenland|Elfenland]] * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] </td> <td valign="top"> * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] </td> <td valign="top"> * [[Gamehelpniagara|Niagara]] * [[Gamehelperudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] </td> <td valign="top"> * [[Gamehelptargi|Targi]] * [[Gamehelpsechsnimmt|Take 5!]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] </td> <td valign="top"> * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> a76a8805eeb0635c6ea49a7fd21be31107a1aa7e Game clock 0 15 1126 164 2014-05-20T09:40:27Z Googol 5621 /* Running out of time */ goes > go wikitext text/x-wiki [[Category:Help]] On '''Board Game Arena''' you are playing "live" (real time). That means you have an allotted delay to play your moves. Most of the time, your initial delay at the beginning of a game is '''3 minutes'''. During each turn, or on specific occasions, you get an additional delay. If you have no more time to play, you will get a penalty and can become eligible to be expelled from the game. == Time to think == Your allotted time to think is displayed on the right of your player's name. When it's your turn to play, this time is also displayed at the top of the web page. == Game speed == Table administrator can make a choice between 4 game speed profile: * Fast * Normal * Slow * Without time limit The additional amount of time credited each turn depends on chosen game speed profile. Be careful to check game speed before game start to adapt your timing. Note: playing without time limit is strongly discouraged, except if you are playing with friends or to discover a new game. Remember that without time limit, you can't expel a player that stops playing. == Running out of time == As soon as you run out of time, you get a clock penalty. If you go over your alloted time by more than 3/4/5 minutes (depending on game speed), any opponent can expel you from the game. Of course, it is strongly advised not to run out of time ... == Move time limit == In addition to your classical time to think, you have a limited time alloted for each move. When it's your turn to play, a red bar appears on top of the web page. It symbolized the remaining time limit for this move. The amount of time depends on game speed. If you go over this limit, you become eligible to be expelled from the game. == "My opponent is too slow" == Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his allotted time to think. If you want to play fast, set up or join table with "fast" mode only, but don't force an opponent to play when he has the right to do so. == "I would like to think a little" == If you are in a critical step of the game and want to take some time to think, you can click on the link "I would like to think a little" on the top right of the page. Thus, your opponents will receive a message and won't be thinking you are away from keyboard. Clicking on this link is not mandatory, but we encourage its use for courtesy. b9ac00f7332fd2be8d85158ad5dac40b230bf01a Rating 0 16 1127 1049 2014-05-20T09:47:43Z Googol 5621 /* How many points do I gain / lose for each game ? */ changed at...place to in...position and less to fewer wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game ? == ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples: * If you end the game in a better position than a player with a higher ELO, you gain a lot of points. * If you end the game in a better position than a player with a lower ELO, you gain fewer points. * If you end the game in a worse position than a player with a lower ELO, you lose a lot points. * And so on... == Some advice == * There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and more good for your ELO. * The game rank is very important to calculate the ELO. This is the reason it is important to continue fighting for the second place during the game if you think you can't win. * The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you lose as many points as if you would finish the game at the last place, plus an additional penalty of 10 points. Even if you are in a difficult situation, your interest is to play the game until the end - or concede the victory to your opponent. == How is my ELO ranking computed ? == The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied. ELO system on BGA has some specificity: * During your first 30 games, your ELO rating is more "elastic": you can win (or lose) more points at each game. This way, your ELO rating converge faster to you "natural" rating. * Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you lose a 2-player game against each opponent before you (in game rank). * Games with more than 2 players last longer. For this reason, there's more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula ! == The formula is exactly one's used by the ELO rating system, with the following adjustments: * First of all, if someone left a game for any reason this game is not taken into account by the ELO rating system. * K=60 for the first 30 games, K=40 afterwards. * K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players". * If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600. == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO 642c5ea7c50e35e5127287c25e46ceac8c2ce09f 1128 1127 2014-05-20T09:52:57Z Googol 5621 /* Some advice */ General tidying up of phraseology. wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game ? == ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples: * If you end the game in a better position than a player with a higher ELO, you gain a lot of points. * If you end the game in a better position than a player with a lower ELO, you gain fewer points. * If you end the game in a worse position than a player with a lower ELO, you lose a lot points. * And so on... == Some advice == * There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and better for your ELO. * Game rank is very important when calculating the ELO. This is the reason it is important to continue fighting for minor places in the game even if you think you can't win. * The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress you lose as many points as if you had finished the game in last place, plus an additional penalty of 10 points. Even if you are in a difficult situation it is in your interest to play the game until the end - or concede the victory to your opponent. == How is my ELO ranking computed ? == The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. The ELO system main principle is the followin: the ELO points difference between 2 players determines the probability of each of them to win the encounter. If two players has the same ELO, their probability to win are 50/50. If one player has 400 more points than the other, his probability to win is 90%. ELO points gains and losses after each game tend to adjust ELO ratings of each player in order this principle is applied. ELO system on BGA has some specificity: * During your first 30 games, your ELO rating is more "elastic": you can win (or lose) more points at each game. This way, your ELO rating converge faster to you "natural" rating. * Original ELO rating system has been designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent after you (in game rank) and that you lose a 2-player game against each opponent before you (in game rank). * Games with more than 2 players last longer. For this reason, there's more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula ! == The formula is exactly one's used by the ELO rating system, with the following adjustments: * First of all, if someone left a game for any reason this game is not taken into account by the ELO rating system. * K=60 for the first 30 games, K=40 afterwards. * K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players". * If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600. == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO 07e3fee5f1846a06143021ceced83b9923f9ef5a 1129 1128 2014-05-20T10:08:46Z Googol 5621 /* How is my ELO ranking computed ? */ Rephrased for clarity, and minor grammatical edits wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game ? == ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples: * If you end the game in a better position than a player with a higher ELO, you gain a lot of points. * If you end the game in a better position than a player with a lower ELO, you gain fewer points. * If you end the game in a worse position than a player with a lower ELO, you lose a lot points. * And so on... == Some advice == * There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and better for your ELO. * Game rank is very important when calculating the ELO. This is the reason it is important to continue fighting for minor places in the game even if you think you can't win. * The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress you lose as many points as if you had finished the game in last place, plus an additional penalty of 10 points. Even if you are in a difficult situation it is in your interest to play the game until the end - or concede the victory to your opponent. == How is my ELO ranking computed ? == The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. The ELO system's main principle is the following: the ELO points difference between 2 players determines the probability of each of them winning an encounter. If two players have the same ELO, they have an equal (50/50) probability of winning. If one player has 400 more points than the other, his probability of winning is 90%. ELO points gains and losses will, over time, tend to adjust the ELO rating of each player to reflect the actual probability that either of them will win a particular encounter. Some changes have been made to the ELO system used on BGA: * During your first 30 games, your ELO rating is more "elastic": you can win (or lose) more points in each game. This way, your ELO rating converges faster to you "natural" rating. * The original ELO rating system was designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent below you (in game rank) and that you lose a 2-player game against each opponent ahead of you (in game rank). * Games with more than 2 players last longer. For this reason, there are more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula ! == The formula is exactly one's used by the ELO rating system, with the following adjustments: * First of all, if someone left a game for any reason this game is not taken into account by the ELO rating system. * K=60 for the first 30 games, K=40 afterwards. * K is multiply by (N/2) for N-players games. If N exceed the "advised number of players" for this game, K is multiply by (A/2), where A is the "advised number of players". * If 2 players has a rating difference greater than 600, we consider that their ELO difference is 600. == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO e83b9fa0d82fc973e9c0577970f8d600c9dba9e5 1130 1129 2014-05-20T10:12:24Z Googol 5621 /* Okay, but I want to know the formula ! */ Verb tense and wording changes wikitext text/x-wiki [[Category:Help]] == What is ELO rating ? == Your ELO rating for a game is your level at this game. It's a 4 digits number followed by sign http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you never play a game on BGA, your initial rating is 1500 . Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game ? == ELO points gains / losses depend on the level of your opponents, and your rank at the end of the game. Some examples: * If you end the game in a better position than a player with a higher ELO, you gain a lot of points. * If you end the game in a better position than a player with a lower ELO, you gain fewer points. * If you end the game in a worse position than a player with a lower ELO, you lose a lot points. * And so on... == Some advice == * There's no use beating players a lot weaker than you (not many points to win). Try to find opponents of your level: it's both more fun and better for your ELO. * Game rank is very important when calculating the ELO. This is the reason it is important to continue fighting for minor places in the game even if you think you can't win. * The number of ELO points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress you lose as many points as if you had finished the game in last place, plus an additional penalty of 10 points. Even if you are in a difficult situation it is in your interest to play the game until the end - or concede the victory to your opponent. == How is my ELO ranking computed ? == The BGA ELO system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system ELO rating system], in use for chess. The ELO system's main principle is the following: the ELO points difference between 2 players determines the probability of each of them winning an encounter. If two players have the same ELO, they have an equal (50/50) probability of winning. If one player has 400 more points than the other, his probability of winning is 90%. ELO points gains and losses will, over time, tend to adjust the ELO rating of each player to reflect the actual probability that either of them will win a particular encounter. Some changes have been made to the ELO system used on BGA: * During your first 30 games, your ELO rating is more "elastic": you can win (or lose) more points in each game. This way, your ELO rating converges faster to you "natural" rating. * The original ELO rating system was designed for 2 player games. For games with more than 2 players, BGA considers (for the ELO rating) that you win a 2-player game against each opponent below you (in game rank) and that you lose a 2-player game against each opponent ahead of you (in game rank). * Games with more than 2 players last longer. For this reason, there are more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula ! == The formula is exactly the one used by the ELO rating system, with the following adjustments: * First of all, if someone leaves a game for any reason this game is not taken into account by the ELO rating system. * K=60 for the first 30 games, K=40 afterwards. * K is multiplied by (N/2) for N-player games. If N exceeds the "advised number of players" for this game, K is multiplied by (A/2), where A is the "advised number of players". * If 2 players have a rating difference greater than 600, we consider that their ELO difference is 600. == Good players, Experts, Masters == * Good players: > 1600 ELO * Experts: > 1800 ELO * Masters: > 2000 ELO 5d77480881080a0400e23a827e79ab09f55cf0be Reputation 0 17 1131 904 2014-05-20T10:13:56Z Googol 5621 /* How to increase my reputation / what makes my reputation decrease ? */ evolved > changes wikitext text/x-wiki [[Category:Help]] == What is reputation ? == On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance. To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items: * Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png) * % of games you finished * % of games you finished with no clock penalties Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits. == How to increase my reputation / what makes my reputation decrease ? == At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks. * a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player. * a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player. You can only give a single thumb (green or red) to a single player. If your opinion changes you can click again on a thumb to reflect this change. As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended to leave the game or to expel this player. By nature, opinions are subjectives. There is nothing we can do for you if you receive a for an unfair reason. However, we know by experience that this system has a lot of advantages and give a relevant information. Qn: its unclear if the "> 10% unfavorable" warning is calculated against the number of "thumbs up / thumbs down".. or "total number of unique players played with / thumbs down". Hope the formula is the latter.. as the first formula will raise many more warnings.. more idiots give thumbs down, and are lazier to give thumb up. == Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png == * Be polite! Say at least "hello" and "good luck" at the beginning of the game, and maybe "good game" ("gg") at the end of the game. * When you need some time to think, click on "I would like to think a little" link. * Always stay calm: it's a game. * Don't press your opponent to play if he has some time left. * If you really can't finish the game (this is not supposed to happen...), then say you are sorry and leave the game (don't wait to get expelled) to save your opponents time. Voluntarily disconnecting and conceding victory to the opponent does not cost you reputation like being expelled does. * Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!). * Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation. == What are the consequences of a bad reputation ? == A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you. It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents. df9767457f600ba8c7ecf88ba7d728f09a673424 1132 1131 2014-05-20T10:17:47Z Googol 5621 /* How to increase my reputation / what makes my reputation decrease ? */ General tidying wikitext text/x-wiki [[Category:Help]] == What is reputation ? == On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance. To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items: * Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png) * % of games you finished * % of games you finished with no clock penalties Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits. == How to increase my reputation / what makes my reputation decrease ? == At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks. * a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player. * a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player. You can only give a single thumb (green or red) to a single player. If your opinion changes you can click again on a thumb to reflect this change. As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended you leave the game or expel this player. By nature, opinions are subjective. There is nothing we can do for you if you receive a "red thumb" for an unfair reason. However, we know by experience that this system has a lot of advantages and generally gives relevant and useful information. Qn: its unclear if the "> 10% unfavorable" warning is calculated against the number of "thumbs up / thumbs down".. or "total number of unique players played with / thumbs down". Hope the formula is the latter.. as the first formula will raise many more warnings.. more idiots give thumbs down, and are lazier to give thumb up. == Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png == * Be polite! Say at least "hello" and "good luck" at the beginning of the game, and maybe "good game" ("gg") at the end of the game. * When you need some time to think, click on "I would like to think a little" link. * Always stay calm: it's a game. * Don't press your opponent to play if he has some time left. * If you really can't finish the game (this is not supposed to happen...), then say you are sorry and leave the game (don't wait to get expelled) to save your opponents time. Voluntarily disconnecting and conceding victory to the opponent does not cost you reputation like being expelled does. * Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!). * Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation. == What are the consequences of a bad reputation ? == A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you. It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents. a62977944d6754893b72089ba91ef3370b0160b7 Faq 0 3 1133 1078 2014-05-20T10:23:36Z Googol 5621 /* What if some player does something wrong? */ Changes for clarity and added "red thumb" wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== You can find many websites where you can play board games with a "turn based" approach: after each move, you have to wait for your opponents to connect to the website and play their own move. Most of the time, you have to wait a long time between each move, and games take a long time to finish (if they ever do). On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. 448115c3c9d6121111339b005feb1dca28b30938 1134 1133 2014-05-22T00:50:37Z Stealthswor 3331 wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play?=== After your opponent takes a move, you are notified that it is your turn (via email or visiting the site). You then go to your game, take your turn, and the process repeats for another player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his alloted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. d8baf4414c3bd3bc32dedb32a979a3385c1c4318 Gamehelptokaido 0 134 1135 1096 2014-05-24T00:02:07Z Benthor 5302 wikitext text/x-wiki == Objetivo del juego == Los jugadores son viajeros en Japón. Seguirán la prestigiosa Tokaido e intentarán hacer del viaje una experiencia tan rica como sea posible Para ello, viajarán a través de magníficos paisajes, degustrán deliciosas especialidades culinarias, comprarán recuerdos, se beneficiarán de las virtudes de las aguas termanles, y tendrán encuentros inolvidables. '''Jugar el juego''' El jugador cuyo viajero sea el más rezagado será quien tomará el siguiente turno. Este jugador deberá mover a su viajero hacia el espacio abierto de su elección, pasando libremente sobre uno o más espacios abiertos. Una vez que haya movido su viajero, el jugador recibirá los beneficios correspondientes a es tipo de espacio. NOTA: Algunos de los espacios en el tablero son dobles. Los espacios dobles se utilizan solo en juegos con 4 o 5 jugadores. == Descripcion de los Espacios == '''Granja''' El jugador gana 3 monedas '''Aguas Termales''' El jugador toma una tarjeta de Aguas Termales. Estas tarjetas vales 2 o 3 puntos. '''Templo''' El jugador debe donar 1, 2 o 3 monedas al templo y obtener 1 punto por cada moneda donada. '''Encuentros''' El jugados roba una carta de Encuentro y recibe un bono: Shokunin - un Recuerdo Annaibito - un Panorama Samurai - 3 Puntos Kuge - 3 Monedas Miko - 1 Punto y 1 Moneda al templo (del banco) '''Pueblo''' El jugador roba 3 tarjetas de recuerdo y puede comprar una o más de esas tarjetas. Cada recuerdo pertenece a uno de los 4 tipos: objetos pequeños, ropa, arte y alimentos y bebidas. Los Recuerdos cuestan 1, 2 ó 3 monedas. Otorgan 1, 3, 5 ó 7 puntos en función de los recuerdos contenidos en la colección del jugador. Cuando compre tarjetas de recuerdo, agrúpelos en conjuntos; cada conjunto puede contener sólo un recuerdo de cada tipo El primer Recuerdo en un conjunto 1. El segundo Recuerdo en un conjunto vale 3 puntos. El tercer Recuerdo en un conjunto vale 5 puntos. El cuarto recuerdo en un conjunto vale 7 puntos. '''Panorámica''' Las panorámicas se componen de 3, 5 ó 5 secciones Cuando un jugador se detiene en una estación panorámica,si aun no tiene ninguna tarjeta de ese tipo de panorámica, toma una tarjeta panorámica de valor «1». De lo contrario, toma el siguiente número en orden ascendente y anota tantos puntos como el valor de la tarjeta. NOTA: Cada viajero puede crear una única panorámica de cada tipo; un viajero que complete una panorámica ya no puede detenerse en los espacios correspondientes a ese tipo (Mar, Montaña o Arroz). '''Posadas''' Todos los viajeros deben detenerse en cada posada. Las posadas son lugares donde los jugadores pueden comprar las tajertas de comida. Estas tienen un costo de 1, 2 ´0 3 monedas y otorgan 6 puntos de victoria. El primer viajero ocupa el espacio más cercano a la carretera, y los viajeros posteriores forman una línea detras de él. Cuando el primer viajero llega a una posada, roba tantas tarjetas de Comida como jugadores existan más 1. Entonces compra la tarjeta de Comida de su elección, pagando su precio. Añade esta tarjeta, boca arriba, a su colección y coloca las tarjetas restantes a un lado del tablero, boca abajo. Luego debe esperar a que los otros viajeros lleguen a la posada. A su llegada, cada viajero comprará una de las tarjetas de Comida restantes. IMPORTANTE: Un viajero no puede probar la misma especialidad culinaria dos veces durante su viaje. Un viajero no puede adquirir más de una tarjeta de Comida por posada. Un viajero no está obigado a comprar una tarjeta de Comida. == '''Fin del Viaje''' == Cuando todos los viajero hayan llegado a Edo. en la última Posada, el juego termina. Los viajeros anotan puntos adicionalres dependiendo de su clasificación como donantes en los templos. El más generoso anota 10 puntos. El segundo anota 7 puntos. El tercero anota 4 puntos. Todos los demás anotan 2 puntos. Otorgar las siguientes tarjetas de logros a los viajeros apropiados. Cada tarjeta de logro vale 3 puntos. Si los jugadores estan empatados en un logro, entonces cada uno recive 3 puntos. Gastrónomo - El jugador con el valor conjunto más alto de las tarjetas de comida. Coleccionita - El jugador con la mayor cantidad de recuerdos. Bañista - El jugador con la mayor cantidad de tarjetas de aguas termales. Parlanchín- El jugador con la mayor cantidad de tarjetas de encuentro. Nota: existen otras 3 tarjetas de logro que se otorgan durante el juego. Una para cada tipo diferente de panorámica y cada unoa se otorga al jugador que sea el primero en completar la panorámica específico. Nota: Si los jugadores están empatados después de la puntuación final, el jugador con más tarjetas de logro gana. ( Extraído del libro de reglas Inglés ) Expansiones Expansión Cruce de Caminos Con esta expansión , cada estación (excepto la Posada) ofrece a los viajeros una nueva opción. Añaden también nuevos viajeros . Las reglas para jugar la expansión Cruce de Caminos se pueden encontrar aquí : http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf Nota: El dado de la fortuna (para los juegos de azar en la granja ) tiene estas caras : x0, x1, x2, x3, x3, x4 Los Nuevos Encuentros Esta expansión añade 4 nuevas tarjetas de Encuentro . La Descripción de las tarjetas está aquí : http://boardgamegeek.com/image/145 f810808a8ea8c8fd3b83d7c96532bd7cabd8a5e8 Main game logic: yourgamename.game.php 0 86 1139 1042 2014-06-08T08:51:18Z Archduke 1630 /* Accessing database */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. a2119e2f3cd991592b766f8dd42655766722d3e2 1146 1139 2014-06-15T21:03:48Z Archduke 1630 /* Notify players */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array. Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. 40ddee7a4cff0e731e4e95424b67b8d149f25577 Gamehelpdudo 0 165 1141 2014-06-11T13:31:38Z Sawyer einherjar 5056 Created page with "Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately for this version of the game there seems to..." wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately for this version of the game there seems to be no English rule book. The link on the game page links to another version of Perudo and consiquently it discusses rules that are not implemented on this BGA version. ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== ''Whenever we use '''he''' it can also be read as '''she''' '' Be the last remaining with at least 1 die in play. If you succeed in being the last player standing with one or more dice in your hand you are the winner! ===Set up=== Each player starts with 5 dice which have the following faces: # Paco icon # value 2 # value 3 # value 4 # value 5 # value 6 Based on the amount of players the game begins with the following number of total dice: <table border="1"> <tr> <td> Nr. players </td> <td> Nr. dice </td> </tr> <tr> <td> 2 </td> <td> 10 </td> </tr> <tr> <td> 3 </td> <td> 15 </td> </tr> <tr> <td> 4 </td> <td> 20 </td> </tr> <tr> <td> 5 </td> <td> 25 </td> </tr> <tr> <td> 6 </td> <td> 30 </td> </tr> </table> ===Round order=== All players roll their dice and check what they rolled. The first player (randomly selected) starts with an opening bid; he proclaims a die value and the amount of dice in the playfield having this exact value. He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos, unless a player is Palifico. After a bid is placed, the turn is passed on to the player on his left, this player has 2 options: # If he thinks that the last bid was wrong he can say "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players must reveal their dice. All dice that match the bid are counted.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game. ====Option 2: increasing the bid==== To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same # increase the value on the die, thus the number of dice stays the same Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts. ===Special rules=== The side of the die with the paco on is special This side counts as a joker for the number of eyes when a Dudo is called. As example: The bid on which a Dudo was called is: 9 dice with a value of 3. <table style="width:300px" border="1"> <caption>''These dice are on the table'' </caption> <tr><td></td><th colspan="6">Die faces</th></tr> <tr><th>Player</th><th>Paco</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th></tr> <tr><td>Mike</td><td>1</td><td>2</td><td>1</td><td>0</td><td>0</td><td>1</td></tr> <tr><td>Lucy</td><td>0</td><td>3</td><td>1</td><td>1</td><td>0</td><td>0</td></tr> <tr><td>John</td><td>3</td><td>0</td><td>1</td><td>0</td><td>0</td><td>1</td></tr> <tr><td>Susan</td><td>1</td><td>0</td><td>1</td><td>1</td><td>1</td><td>1</td></tr> </table> There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. The Bid is thus valid and the player who called Dudo loses a die. As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up. Example: from 9 dice with a value of 3 one can make a bid of 5 (9/2=4.5 -rounding up->5) dice with a paco. The Next player can now choose to either # Increase the number of dice with a paco # Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra. Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. (or thus any number of dice exceeding 11) ===Palifico=== The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated). ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza. If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid. </li></ol> 7683462768ba7fc257121936dccfd3c46cc1aa2d 1142 1141 2014-06-11T13:34:50Z Sawyer einherjar 5056 wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately for this version of the game there seems to be no English rule book. The link on the game page links to another version of Perudo and consiquently it discusses rules that are not implemented on this BGA version. ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== ''Whenever we use '''he''' it can also be read as '''she''' '' Be the last remaining with at least 1 die in play. If you succeed in being the last player standing with one or more dice in your hand you are the winner! ===Set up=== Each player starts with 5 dice which have the following faces: # Paco # value 2 # value 3 # value 4 # value 5 # value 6 Based on the amount of players the game begins with the following number of total dice: <table border="1"> <tr> <td> Nr. players </td> <td> Nr. dice </td> </tr> <tr> <td> 2 </td> <td> 10 </td> </tr> <tr> <td> 3 </td> <td> 15 </td> </tr> <tr> <td> 4 </td> <td> 20 </td> </tr> <tr> <td> 5 </td> <td> 25 </td> </tr> <tr> <td> 6 </td> <td> 30 </td> </tr> </table> ===Round order=== All players roll their dice and check what they rolled. The first player (randomly selected) starts with an opening bid; he proclaims a die value and the amount of dice in the playfield having this exact value. He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos, unless a player is Palifico. After a bid is placed, the turn is passed on to the player on his left, this player has 2 options: # If he thinks that the last bid was wrong he can say "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players must reveal their dice. All dice that match the bid are counted.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game. ====Option 2: increasing the bid==== To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same # increase the value on the die, thus the number of dice stays the same Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts. ===Special rules=== The side of the die with the paco on is special This side counts as a joker for the number of eyes when a Dudo is called. As example: The bid on which a Dudo was called is: 9 dice with a value of 3. <table style="width:300px" border="1"> <caption>''These dice are on the table'' </caption> <tr><td></td><th colspan="6">Die faces</th></tr> <tr><th>Player</th><th>Paco</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th></tr> <tr><td>Mike</td><td>1</td><td>2</td><td>1</td><td>0</td><td>0</td><td>1</td></tr> <tr><td>Lucy</td><td>0</td><td>3</td><td>1</td><td>1</td><td>0</td><td>0</td></tr> <tr><td>John</td><td>3</td><td>0</td><td>1</td><td>0</td><td>0</td><td>1</td></tr> <tr><td>Susan</td><td>1</td><td>0</td><td>1</td><td>1</td><td>1</td><td>1</td></tr> </table> There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. The Bid is thus valid and the player who called Dudo loses a die. As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up. Example: from 9 dice with a value of 3 one can make a bid of 5 (9/2=4.5 -rounding up->5) dice with a paco. The Next player can now choose to either # Increase the number of dice with a paco # Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra. Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. (or thus any number of dice exceeding 11) ===Palifico=== The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated). ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza. If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid. </li></ol> bafe9de8554b3d55d33f65ce792559de987f6608 1144 1142 2014-06-12T08:44:52Z Sawyer einherjar 5056 wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consiquently it discusses rules that are not implemented on this BGA version. ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== ''Whenever we use '''he''' it can also be read as '''she''' '' Be the last remaining with at least 1 die in play. If you succeed in being the last player standing with one or more dice in your hand you are the winner! ===Set up=== Each player starts with 5 dice which have the following faces: # Paco # value 2 # value 3 # value 4 # value 5 # value 6 Based on the amount of players the game begins with the following number of total dice: <table border="1"> <tr> <td> Nr. players </td> <td> Nr. dice </td> </tr> <tr> <td> 2 </td> <td> 10 </td> </tr> <tr> <td> 3 </td> <td> 15 </td> </tr> <tr> <td> 4 </td> <td> 20 </td> </tr> <tr> <td> 5 </td> <td> 25 </td> </tr> <tr> <td> 6 </td> <td> 30 </td> </tr> </table> ===Round order=== All players roll their dice and check what they rolled. The first player (randomly selected) starts with an opening bid; he proclaims a die value and the amount of dice in the playfield having this exact value. He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos, unless a player is Palifico. After a bid is placed, the turn is passed on to the player on his left, this player has 2 options: # If he thinks that the last bid was wrong he can say "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players must reveal their dice. All dice that match the bid are counted.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game. ====Option 2: increasing the bid==== To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same # increase the value on the die, thus the number of dice stays the same Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts. ===Special rules=== The side of the die with the paco on is special This side counts as a joker for the number of eyes when a Dudo is called. As example: The bid on which a Dudo was called is: 9 dice with a value of 3. <table style="width:300px" border="1"> <caption>''These dice are on the table'' </caption> <tr><td></td><th colspan="6">Die faces</th></tr> <tr><th>Player</th><th>Paco</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th></tr> <tr><td>Mike</td><td>1</td><td>2</td><td>1</td><td>0</td><td>0</td><td>1</td></tr> <tr><td>Lucy</td><td>0</td><td>3</td><td>1</td><td>1</td><td>0</td><td>0</td></tr> <tr><td>John</td><td>3</td><td>0</td><td>1</td><td>0</td><td>0</td><td>1</td></tr> <tr><td>Susan</td><td>1</td><td>0</td><td>1</td><td>1</td><td>1</td><td>1</td></tr> </table> There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die. As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up. Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco. The Next player can now choose to either # Increase the number of dice with a paco # Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra. Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11) ===Palifico=== The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated). ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza. If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid. </li></ol> 3798116e81fb42ef58cf304c534dbef6361e61eb Your game state machine: states.inc.php 0 90 1147 1043 2014-06-16T09:38:51Z Archduke 1630 /* Private infos in args */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "args" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> === args === (optional) From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state. Example 1 : for Reversi, the list of possible moves during playerTurn state. Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor. Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them. In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them. Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array. Let's see a complete example using args with « Reversi » game : In states.inc.php, we specify some « args » argument for gamestate « playerTurn » : <pre> 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", <================================== HERE "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), </pre> It corresponds to a « argPlayerTurn » method in our PHP code (reversi.game.php): <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves() ); } </pre> Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn : <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> Note: you can also use values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above). Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn). ==== Private infos in args ==== By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic. This is although possible to specify that some data should be sent to some specific players only: Example 1: send an information to active player(s) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private 'active' => array( // Using "active" keyword inside "_private", you select active player(s) 'somePrivateData' => self::getSomePrivateData() // will be send only to active player(s) ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> Inside the js file, these variables will be available through `args._private`. (e.g. `args._private.somePrivateData` -- it is not `args._private.active.somePrivateData` nor is it `args.somePrivateData`) Example 2: send an information to a specific player (<specific_player_id>) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private <specific_player_id> => array( // you select one specific player with its id 'somePrivateData' => self::getSomePrivateData() // will be send only to <specific_player_id> ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> IMPORTANT: in certain situation (ex: multipleactiveplayer game state) these "private data" features can have a big performance impact. Please do not use if not needed. === updateGameProgression === (optional) IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated. At least one of your game state (any of them) must specify updateGameProgression=>true. 3d5baa08e143d2d429f6e0839815cec9d68de18d 1149 1147 2014-06-18T23:04:42Z Pikiou 1872 /* id */ potential crash on active games when ID is changed wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. Note: When a game is in prod and you change the ID of a state, all active games (including many turn based) will behave unpredictably. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "args" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> === args === (optional) From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state. Example 1 : for Reversi, the list of possible moves during playerTurn state. Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor. Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them. In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them. Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array. Let's see a complete example using args with « Reversi » game : In states.inc.php, we specify some « args » argument for gamestate « playerTurn » : <pre> 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", <================================== HERE "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), </pre> It corresponds to a « argPlayerTurn » method in our PHP code (reversi.game.php): <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves() ); } </pre> Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn : <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> Note: you can also use values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above). Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn). ==== Private infos in args ==== By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic. This is although possible to specify that some data should be sent to some specific players only: Example 1: send an information to active player(s) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private 'active' => array( // Using "active" keyword inside "_private", you select active player(s) 'somePrivateData' => self::getSomePrivateData() // will be send only to active player(s) ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> Inside the js file, these variables will be available through `args._private`. (e.g. `args._private.somePrivateData` -- it is not `args._private.active.somePrivateData` nor is it `args.somePrivateData`) Example 2: send an information to a specific player (<specific_player_id>) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private <specific_player_id> => array( // you select one specific player with its id 'somePrivateData' => self::getSomePrivateData() // will be send only to <specific_player_id> ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> IMPORTANT: in certain situation (ex: multipleactiveplayer game state) these "private data" features can have a big performance impact. Please do not use if not needed. === updateGameProgression === (optional) IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated. At least one of your game state (any of them) must specify updateGameProgression=>true. 225c5e46634edd5833523ae11fee333980125407 Translations 0 94 1150 836 2014-06-23T22:43:35Z Jinnh 4158 wikitext text/x-wiki Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them. == How translation works? == When developing your game, all strings must be in English. Strings must be coherent with the English version of the game. Before the release of the game, BGA team will do the French translation of the game. After the release of the game, the BGA players community will translate the game in every language. == What should be translated? == Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ... This does NOT include error messages that are not supposed to happened (unexpected errors). == Focus on translating notifications == Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function. However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side. == WARNING: how to make sure your strings will be translated == For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers). If your original string is not "physically" inside one of this marker, it won't be translated. <pre> // Examples: the following strings will be translated: var mystring_translated = _("my string"); // JS $mystring_translated = self::_("my string"); // PHP $mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP // Examples: the following strings WILL NOT be translated: $my_string = "my string"; $not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation $not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing </pre> == How to not make translators crazy ;) == * When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings. * Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it). * Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like: <pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre> Write instead: <pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre> (or the equivalent "dojo.string.substitute" in Javascript) * When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings. * The BGA translation policy is to be flexible on grammar... We prefer to write "player gets 1 coin(s)" than write two versions of the same string for plural and singular - it reduces the number of strings to translate. * Instead of writing nice strings like "With the effect of ZZZ, player XXX gets a new YYY", which is very difficult to translate, write strings like "ZZZ: XXX gets YYY". == On client side (Javascript) == On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate. Examples: <pre> // Get a string in player's language: var translated = _("original english string"); // Get a string in player's language with parameter: var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", { p: 2, d: 4 } ); </pre> '''WARNING:''' in Javascript strings to translate, you should never use '\n', '\t' or such, as it will break the translation bundle and result in all the Javascript translation to fail. In any case, the strings will result in HTML code, and such character codes won't have any impact on the HTML rendering. You should use HTML markup instead. == On server side (PHP) == On PHP side, you can use 3 different functions to specify that a string must be translated. '''clienttranslate( "my string to translate" ):''' This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side. In general, you use clienttranslate: * On your states.inc.php, for field "description" and "descriptionmyturn". <pre> "description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'), </pre> * On "material.inc.php", when defining texts for game material that must be displayed on client side. <pre> $this->card_types = array( 1 => array( 'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side. </pre> * When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation. <pre> // A game log string with no argument: self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() ); </pre> Translating arguments is a little bit more complex. It is using the "i18n" special argument as below: <pre> // In the following example, we translate the game log itself, but also the "card_name" argument: self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array( 'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'points' => $points, 'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string. ) ); </pre> <note>Pay attention when using 'i18n' argument when translating argument for client : do NOT use same argument for both translation AND key code for client side action (like using 'card_name' to move it on player board as described in the example). It's pretty obvious in the example, but it can be very tricky when translation is made at the end of the development (which is often the case). Use explicit argument name like 'card_name_translated' by example.</note> '''self::_( "my string to translate" ):''' This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player). Most of the time, you don't need to translate strings on server side, except on the following 3 situations: * When throwing an exception because the player did a forbidden move. <pre> // This will display a translatable red message to the player that just do some wrong action: throw new BgaUserException( self::_('You must choose 3 cards') ); // ... notice the use of BgaUserException that signals that this exception is "expected". In theory, all exception that are expected should be translated. </pre> * In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file. <pre> $this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II"); </pre> * Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions. <pre> // In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this: throw new BgaUserException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'] ); </pre> * Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user. '''totranslate( "my string to translate" ):''' This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side. You should not use this function, except on the following cases: * Statistics name in stats.inc.php * Option names and option values name in gameoptions.inc.php 6d9653cdcceabe0c9cd666fd9540128fc590cb6a 1151 1150 2014-06-23T22:43:56Z Jinnh 4158 wikitext text/x-wiki Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them. == How translation works? == When developing your game, all strings must be in English. Strings must be coherent with the English version of the game. Before the release of the game, BGA team will do the French translation of the game. After the release of the game, the BGA players community will translate the game in every language. == What should be translated? == Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ... This does NOT include error messages that are not supposed to happened (unexpected errors). == Focus on translating notifications == Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function. However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side. == WARNING: how to make sure your strings will be translated == For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers). If your original string is not "physically" inside one of this marker, it won't be translated. <pre> // Examples: the following strings will be translated: var mystring_translated = _("my string"); // JS $mystring_translated = self::_("my string"); // PHP $mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP // Examples: the following strings WILL NOT be translated: $my_string = "my string"; $not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation $not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing </pre> == How to not make translators crazy ;) == * When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings. * Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it). * Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like: <pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre> Write instead: <pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre> (or the equivalent "dojo.string.substitute" in Javascript) * When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings. * The BGA translation policy is to be flexible on grammar... We prefer to write "player gets 1 coin(s)" than write two versions of the same string for plural and singular - it reduces the number of strings to translate. * Instead of writing nice strings like "With the effect of ZZZ, player XXX gets a new YYY", which is very difficult to translate, write strings like "ZZZ: XXX gets YYY". == On client side (Javascript) == On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate. Examples: <pre> // Get a string in player's language: var translated = _("original english string"); // Get a string in player's language with parameter: var translated = dojo.string.substitute( "You can pick ${p} cards and discard ${d}", { p: 2, d: 4 } ); </pre> '''WARNING:''' in Javascript strings to translate, you should never use '\n', '\t' or such, as it will break the translation bundle and result in all the Javascript translation to fail. In any case, the strings will result in HTML code, and such character codes won't have any impact on the HTML rendering. You should use HTML markup instead. == On server side (PHP) == On PHP side, you can use 3 different functions to specify that a string must be translated. '''clienttranslate( "my string to translate" ):''' This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side. In general, you use clienttranslate: * On your states.inc.php, for field "description" and "descriptionmyturn". <pre> "description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'), </pre> * On "material.inc.php", when defining texts for game material that must be displayed on client side. <pre> $this->card_types = array( 1 => array( 'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side. </pre> * When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation. <pre> // A game log string with no argument: self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() ); </pre> Translating arguments is a little bit more complex. It is using the "i18n" special argument as below: <pre> // In the following example, we translate the game log itself, but also the "card_name" argument: self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array( 'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'points' => $points, 'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string. ) ); </pre> Pay attention when using 'i18n' argument when translating argument for client : do NOT use same argument for both translation AND key code for client side action (like using 'card_name' to move it on player board as described in the example). It's pretty obvious in the example, but it can be very tricky when translation is made at the end of the development (which is often the case). Use explicit argument name like 'card_name_translated' by example. '''self::_( "my string to translate" ):''' This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player). Most of the time, you don't need to translate strings on server side, except on the following 3 situations: * When throwing an exception because the player did a forbidden move. <pre> // This will display a translatable red message to the player that just do some wrong action: throw new BgaUserException( self::_('You must choose 3 cards') ); // ... notice the use of BgaUserException that signals that this exception is "expected". In theory, all exception that are expected should be translated. </pre> * In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file. <pre> $this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II"); </pre> * Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions. <pre> // In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this: throw new BgaUserException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'] ); </pre> * Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user. '''totranslate( "my string to translate" ):''' This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side. You should not use this function, except on the following cases: * Statistics name in stats.inc.php * Option names and option values name in gameoptions.inc.php 96da7c625db8ae8e5af16cf821169c59add4e14f Gamehelptokaido 0 134 1152 1135 2014-07-02T12:06:32Z Xenom 5998 wikitext text/x-wiki == Objetivo del juego == Los jugadores son viajeros en Japón. Seguirán la prestigiosa Tokaido e intentarán hacer del viaje una experiencia tan rica como sea posible. Para ello, viajarán a través de magníficos paisajes, degustarán deliciosas especialidades culinarias, comprarán recuerdos, se beneficiarán de las virtudes de las aguas termales, y tendrán encuentros inolvidables. ==Jugar el juego== El jugador cuyo viajero sea el más rezagado será quien tomará el siguiente turno. Este jugador deberá mover a su viajero hacia el espacio abierto de su elección, pasando libremente sobre uno o más espacios abiertos. Una vez que haya movido su viajero, el jugador recibirá los beneficios correspondientes a es tipo de espacio. NOTA: Algunos de los espacios en el tablero son dobles. Los espacios dobles se utilizan solo en juegos con 4 o 5 jugadores. ===Descripción de los Espacios=== ====Granja==== El jugador gana 3 monedas. ====Aguas Termales==== El jugador toma una tarjeta de Aguas Termales. Estas tarjetas valen 2 ó 3 puntos. ====Templo==== El jugador debe donar 1, 2 ó 3 monedas al templo y obtener 1 punto por cada moneda donada. ====Encuentros==== El jugados roba una carta de Encuentro y recibe un bono: Shokunin - un Recuerdo Annaibito - un Panorama Samurai - 3 Puntos Kuge - 3 Monedas Miko - 1 Punto y 1 Moneda al templo (del banco) ====Pueblo==== El jugador roba 3 tarjetas de recuerdo y puede comprar una o más de esas tarjetas. Cada recuerdo pertenece a uno de los 4 tipos: objetos pequeños, ropa, arte y alimentos y bebidas. Los Recuerdos cuestan 1, 2 ó 3 monedas. Otorgan 1, 3, 5 ó 7 puntos en función de los recuerdos contenidos en la colección del jugador. Cuando se compran tarjetas de recuerdo, se agrupan en conjuntos; cada conjunto puede contener sólo un recuerdo de cada tipo: El primer Recuerdo en un conjunto 1 punto. El segundo Recuerdo en un conjunto vale 3 puntos. El tercer Recuerdo en un conjunto vale 5 puntos. El cuarto recuerdo en un conjunto vale 7 puntos. ====Panorámica==== Las panorámicas se componen de 3, 4 ó 5 secciones Cuando un jugador se detiene en una estación panorámica, roba la carta de valor 1 si es la primera vez que se detiene, si ya la tiene roba la de coste superior. Es decir, la primera vez que se detiene roba la de valor 1, la segunda la de 2, la tercera la de 3, etc. NOTA: Cada viajero puede crear una única panorámica de cada tipo; un viajero que complete una panorámica ya no puede detenerse en los espacios correspondientes a ese tipo (Mar, Montaña o Arroz). ====Posadas==== Todos los viajeros deben detenerse en cada posada. Las posadas son lugares donde los jugadores pueden comprar las tajertas de comida. Estas tienen un costo de 1, 2 ´0 3 monedas y otorgan 6 puntos de victoria. El primer viajero ocupa el espacio más cercano a la carretera, y los viajeros posteriores forman una línea detrás de él. Cuando el primer viajero llega a una posada, roba tantas tarjetas de Comida como jugadores existan más 1. Entonces compra la tarjeta de Comida de su elección, pagando su precio. Añade esta tarjeta, boca arriba, a su colección y coloca las tarjetas restantes a un lado del tablero, boca abajo. Luego debe esperar a que los otros viajeros lleguen a la posada. A su llegada, cada viajero comprará una de las tarjetas de Comida restantes. IMPORTANTE: Un viajero no puede probar la misma especialidad culinaria dos veces durante su viaje. Un viajero no puede adquirir más de una tarjeta de Comida por posada. Un viajero no está obligado a comprar una tarjeta de Comida. ===Fin del Viaje=== Cuando todos los viajero hayan llegado a Edo. en la última Posada, el juego termina. Los viajeros anotan puntos adicionales dependiendo de su clasificación como donantes en los templos. El más generoso anota 10 puntos. El segundo anota 7 puntos. El tercero anota 4 puntos. Todos los demás anotan 2 puntos. Otorgar las siguientes tarjetas de logros a los viajeros apropiados. Cada tarjeta de logro vale 3 puntos. Si los jugadores están empatados en un logro, entonces cada uno recibe 3 puntos. Gastrónomo - El jugador con el valor conjunto más alto de las tarjetas de comida. Coleccionista - El jugador con la mayor cantidad de recuerdos. Bañista - El jugador con la mayor cantidad de tarjetas de aguas termales. Parlanchín- El jugador con la mayor cantidad de tarjetas de encuentro. Nota: existen otras 3 tarjetas de logro que se otorgan durante el juego. Una para cada tipo diferente de panorámica y cada una se otorga al jugador que sea el primero en completar la panorámica específica. Nota: Si los jugadores están empatados después de la puntuación final, el jugador con más tarjetas de logro gana. ( Extraído del libro de reglas Inglés ) Expansiones Expansión Cruce de Caminos Con esta expansión , cada estación (excepto la Posada) ofrece a los viajeros una nueva opción. Añaden también nuevosviajeros . Las reglas para jugar la expansión Cruce de Caminos se pueden encontrar aquí : http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf Nota: El dado de la fortuna (para los juegos de azar en la granja ) tiene estas caras : x0, x1, x2, x3, x3, x4 Los Nuevos Encuentros Esta expansión añade 4 nuevas tarjetas de Encuentro . La Descripción de las tarjetas está aquí : http://boardgamegeek.com/image/145 8470092b2b13eae69c5febc2132ca6a85562b973 1193 1152 2014-08-06T23:54:55Z Runtly 6144 Undo revision 1152 by [[Special:Contributions/Xenom|Xenom]] ([[User talk:Xenom|talk]]) Spanish translation ended up on English page wikitext text/x-wiki == Objetivo del juego == Los jugadores son viajeros en Japón. Seguirán la prestigiosa Tokaido e intentarán hacer del viaje una experiencia tan rica como sea posible Para ello, viajarán a través de magníficos paisajes, degustrán deliciosas especialidades culinarias, comprarán recuerdos, se beneficiarán de las virtudes de las aguas termanles, y tendrán encuentros inolvidables. '''Jugar el juego''' El jugador cuyo viajero sea el más rezagado será quien tomará el siguiente turno. Este jugador deberá mover a su viajero hacia el espacio abierto de su elección, pasando libremente sobre uno o más espacios abiertos. Una vez que haya movido su viajero, el jugador recibirá los beneficios correspondientes a es tipo de espacio. NOTA: Algunos de los espacios en el tablero son dobles. Los espacios dobles se utilizan solo en juegos con 4 o 5 jugadores. == Descripcion de los Espacios == '''Granja''' El jugador gana 3 monedas '''Aguas Termales''' El jugador toma una tarjeta de Aguas Termales. Estas tarjetas vales 2 o 3 puntos. '''Templo''' El jugador debe donar 1, 2 o 3 monedas al templo y obtener 1 punto por cada moneda donada. '''Encuentros''' El jugados roba una carta de Encuentro y recibe un bono: Shokunin - un Recuerdo Annaibito - un Panorama Samurai - 3 Puntos Kuge - 3 Monedas Miko - 1 Punto y 1 Moneda al templo (del banco) '''Pueblo''' El jugador roba 3 tarjetas de recuerdo y puede comprar una o más de esas tarjetas. Cada recuerdo pertenece a uno de los 4 tipos: objetos pequeños, ropa, arte y alimentos y bebidas. Los Recuerdos cuestan 1, 2 ó 3 monedas. Otorgan 1, 3, 5 ó 7 puntos en función de los recuerdos contenidos en la colección del jugador. Cuando compre tarjetas de recuerdo, agrúpelos en conjuntos; cada conjunto puede contener sólo un recuerdo de cada tipo El primer Recuerdo en un conjunto 1. El segundo Recuerdo en un conjunto vale 3 puntos. El tercer Recuerdo en un conjunto vale 5 puntos. El cuarto recuerdo en un conjunto vale 7 puntos. '''Panorámica''' Las panorámicas se componen de 3, 5 ó 5 secciones Cuando un jugador se detiene en una estación panorámica,si aun no tiene ninguna tarjeta de ese tipo de panorámica, toma una tarjeta panorámica de valor «1». De lo contrario, toma el siguiente número en orden ascendente y anota tantos puntos como el valor de la tarjeta. NOTA: Cada viajero puede crear una única panorámica de cada tipo; un viajero que complete una panorámica ya no puede detenerse en los espacios correspondientes a ese tipo (Mar, Montaña o Arroz). '''Posadas''' Todos los viajeros deben detenerse en cada posada. Las posadas son lugares donde los jugadores pueden comprar las tajertas de comida. Estas tienen un costo de 1, 2 ´0 3 monedas y otorgan 6 puntos de victoria. El primer viajero ocupa el espacio más cercano a la carretera, y los viajeros posteriores forman una línea detras de él. Cuando el primer viajero llega a una posada, roba tantas tarjetas de Comida como jugadores existan más 1. Entonces compra la tarjeta de Comida de su elección, pagando su precio. Añade esta tarjeta, boca arriba, a su colección y coloca las tarjetas restantes a un lado del tablero, boca abajo. Luego debe esperar a que los otros viajeros lleguen a la posada. A su llegada, cada viajero comprará una de las tarjetas de Comida restantes. IMPORTANTE: Un viajero no puede probar la misma especialidad culinaria dos veces durante su viaje. Un viajero no puede adquirir más de una tarjeta de Comida por posada. Un viajero no está obigado a comprar una tarjeta de Comida. == '''Fin del Viaje''' == Cuando todos los viajero hayan llegado a Edo. en la última Posada, el juego termina. Los viajeros anotan puntos adicionalres dependiendo de su clasificación como donantes en los templos. El más generoso anota 10 puntos. El segundo anota 7 puntos. El tercero anota 4 puntos. Todos los demás anotan 2 puntos. Otorgar las siguientes tarjetas de logros a los viajeros apropiados. Cada tarjeta de logro vale 3 puntos. Si los jugadores estan empatados en un logro, entonces cada uno recive 3 puntos. Gastrónomo - El jugador con el valor conjunto más alto de las tarjetas de comida. Coleccionita - El jugador con la mayor cantidad de recuerdos. Bañista - El jugador con la mayor cantidad de tarjetas de aguas termales. Parlanchín- El jugador con la mayor cantidad de tarjetas de encuentro. Nota: existen otras 3 tarjetas de logro que se otorgan durante el juego. Una para cada tipo diferente de panorámica y cada unoa se otorga al jugador que sea el primero en completar la panorámica específico. Nota: Si los jugadores están empatados después de la puntuación final, el jugador con más tarjetas de logro gana. ( Extraído del libro de reglas Inglés ) Expansiones Expansión Cruce de Caminos Con esta expansión , cada estación (excepto la Posada) ofrece a los viajeros una nueva opción. Añaden también nuevos viajeros . Las reglas para jugar la expansión Cruce de Caminos se pueden encontrar aquí : http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf Nota: El dado de la fortuna (para los juegos de azar en la granja ) tiene estas caras : x0, x1, x2, x3, x3, x4 Los Nuevos Encuentros Esta expansión añade 4 nuevas tarjetas de Encuentro . La Descripción de las tarjetas está aquí : http://boardgamegeek.com/image/145 f810808a8ea8c8fd3b83d7c96532bd7cabd8a5e8 1194 1193 2014-08-06T23:55:33Z Runtly 6144 Undo revision 1135 by [[Special:Contributions/Benthor|Benthor]] ([[User talk:Benthor|talk]]) Spanish translation ended up on English page wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They will follow the prestigious Tokaido and try to make this journey as rich an experience as possible. To do this, they will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== '''Farm''' : The player earns 3 coins. '''Hot Spring''' : The player takes a Hot Spring card. These cards are worth 2 or 3 points. '''Temple''' : The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. '''Encounters''' : The player draws one Encounter card and receives a bonus: :* Shokunin - one Souvenir :* Annaibito - one Panorama :* Samurai - 3 points :* Kuge - 3 coins :* Miko - 1 point and 1 coin to the Temple (from the bank) '''Village''' : The player draws 3 Souvenir cards and can purchase one or more of these cards. : Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks. : Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection. : As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type. :* The first Souvenir in a set is worth 1 point. :* The second Souvenir in a set is worth 3 points. :* The third Souvenir in a set is worth 5 points. :* The fourth Souvenir in a set is worth 7 points. '''Panorama''' : Panoramas are made of 3, 4 or 5 sections. : When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ». : Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card. : '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy). '''Inns''' : All Travelers must stop at each Inn. : The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points. : The first traveler occupies the space nearest the road, and later travelers form a line after him. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. : He can then purchase one Meal card of his choice by paying its price. : He adds this card, face up, to his collection and places the remaining cards next to the board, face down. : He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards. : '''IMPORTANT:''' :* A traveler cannot taste the same culinary specialty twice during his journey. :* A traveler can never purchase more than one Meal card per Inn. :* A traveler is never obliged to purchase a Meal card. == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added. Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf Note: The Fortune die (for gambling at the farm) has these faces: x0, x1, x2, x3, x3, x4 == The New Encounters == This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large 1c97478bd1c3715be28d901489239d5133e5bc2a Help 0 4 1153 1148 2014-07-04T10:34:36Z Sawyer einherjar 5056 the hyperlink to perduo was fault wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpeightmastersrevenge|8 Master's revenge]] * [[Gamehelpelfenland|Elfenland]] * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] </td> <td valign="top"> * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] </td> <td valign="top"> * [[Gamehelpniagara|Niagara]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] </td> <td valign="top"> * [[Gamehelptargi|Targi]] * [[Gamehelpsechsnimmt|Take 5!]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] </td> <td valign="top"> * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> 0ee543bd56e2d6f5fcf33341ae09fa0d34fd91ad Gamehelpdiams 0 38 1154 153 2014-07-05T09:43:36Z Magposunnie 5907 /* Goal */ wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round : * for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) * and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2nd gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2nd round who will get the victory) == Rules summary == On your turn, you must first choose between two 'draw actions' (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two 'play actions' (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color than the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty ended... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will lose yours!) '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (but of course, if your opponent doesn't have any diamond of this kind, drilling will fail!) '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game!''' fa8b4f0cb77ad48f727d7bb6ad3437e72e960a8f 1155 1154 2014-07-05T09:45:07Z Magposunnie 5907 /* Rules summary */ wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round : * for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) * and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2nd gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2nd round who will get the victory) == Rules summary == On your turn, you must first choose between two 'draw actions' (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two 'play actions' (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color as the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty handed... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will lose yours!) '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (but of course, if your opponent doesn't have any diamond of this kind, drilling will fail!) '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game!''' 08c4b3313b141e3cf1f4c1569b7b3d3152716a53 1156 1155 2014-07-05T09:46:42Z Magposunnie 5907 /* Rules summary */ wikitext text/x-wiki == Goal == Secure as many '''diamond collections''' as you can in your safe! A collection is a set of three diamonds of the same color, or more (up to five). Each color has a matching 'quality' digit ranging from 1 to 10. Collections are worth more or less depending upon the diamond color and the number of diamonds (be careful to check the collection values, the most valuable diamond is '7', not '10'). Bonus points will be earned at the end of the round : * for the player with the most diamonds of exceptional purity (magnifying glass symbol) in his safe (5 bonus points, 2 points in case of a tie) * and for the player whose digits for the diamonds still in hand sum up to the biggest value (3 bonus points, tie or no tie). On each round, you'll earn victory chips based on the points earned collecting diamonds (the 1st player gets 4 chips, the 2nd gets 3 chips and so on). The player with the '''most victory chips''' at the end of three rounds wins! (in case of a tie, it's the player who won the 2nd round who will get the victory) == Rules summary == On your turn, you must first choose between two 'draw actions' (phase 1): * Draw one card and put it in your hand * Draw two cards and put them on the market. Then you will have to choose between two 'play actions' (phase 2): * Select one of your cards and go to the market with it. Once on the market, you can: ** Take all cards of the same color as the one you went to the market with (including it) ** Take a selection of cards whose digits sum up to the digit of the card you went to the market with ** Or come back empty-handed... * Select cards in your hand and secure them into your safe. In order to be valid, your selection: ** Must contain at least one collection (three diamonds of the same color) ** Can contain diamonds matching a collection already present in your safe (in order to expand the collection) At the end of your turn, if you have more than 5 cards in your hand, you will have to discard some to keep only 5. == Special cards == Three special cards give you the power to play tricks on your opponents '''instead of playing phase 2'''. Each of these cards can be used either with the 'Compulsory sale' power that they all share, or with their other (and unique) power. Power effects are as follows: '''Compulsory sale''' enables you to get all diamonds of a quality that you have in your hand from the market ''after'' forcing an opponent to put all his diamonds of this quality on the market (but be careful! If he doesn't have any, you will lose yours!) '''Secur`express''' enables you to secure diamonds of one quality already present in your safe '''Safe drilling''' enables you to get a diamond of a given quality and purity, straight from the safe of an opponent (but of course, if your opponent doesn't have any diamond of this kind, drilling will fail!) '''Sleight of hand''' enables you to take any diamond you want from the market, just like that! == Available variants == '''Game length''': the 'Standard' game is played in 3 rounds. The 'Quick game' variant makes it possible to play a game in just one round when you are in a hurry to get lots of pretty diamonds to pay back your Can't stop gambling debts! '''Closing card''': in the 'Standard' game, the closing card is randomly shuffled among the last 15 cards at 2/3 players, and among the last 5 cards at 4/5 players. With the 'Deterministic' variant, the closing card is the last one, so you can try to outthink your opponents till the very end! '''Have a good game!''' dfb28ed3f68fa98582c08b8b38661b359a57ca53 Gamehelpdudo 0 165 1157 1144 2014-07-05T12:40:10Z Wolfkin 3936 /* Goal of the Game */ moving to top.. this exception isn't part of the goals of the game wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consiquently it discusses rules that are not implemented on this BGA version. ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing with one or more dice in your hand you are the winner! ===Set up=== Each player starts with 5 dice which have the following faces: # Paco # value 2 # value 3 # value 4 # value 5 # value 6 Based on the amount of players the game begins with the following number of total dice: <table border="1"> <tr> <td> Nr. players </td> <td> Nr. dice </td> </tr> <tr> <td> 2 </td> <td> 10 </td> </tr> <tr> <td> 3 </td> <td> 15 </td> </tr> <tr> <td> 4 </td> <td> 20 </td> </tr> <tr> <td> 5 </td> <td> 25 </td> </tr> <tr> <td> 6 </td> <td> 30 </td> </tr> </table> ===Round order=== All players roll their dice and check what they rolled. The first player (randomly selected) starts with an opening bid; he proclaims a die value and the amount of dice in the playfield having this exact value. He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos, unless a player is Palifico. After a bid is placed, the turn is passed on to the player on his left, this player has 2 options: # If he thinks that the last bid was wrong he can say "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players must reveal their dice. All dice that match the bid are counted.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game. ====Option 2: increasing the bid==== To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same # increase the value on the die, thus the number of dice stays the same Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts. ===Special rules=== The side of the die with the paco on is special This side counts as a joker for the number of eyes when a Dudo is called. As example: The bid on which a Dudo was called is: 9 dice with a value of 3. <table style="width:300px" border="1"> <caption>''These dice are on the table'' </caption> <tr><td></td><th colspan="6">Die faces</th></tr> <tr><th>Player</th><th>Paco</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th></tr> <tr><td>Mike</td><td>1</td><td>2</td><td>1</td><td>0</td><td>0</td><td>1</td></tr> <tr><td>Lucy</td><td>0</td><td>3</td><td>1</td><td>1</td><td>0</td><td>0</td></tr> <tr><td>John</td><td>3</td><td>0</td><td>1</td><td>0</td><td>0</td><td>1</td></tr> <tr><td>Susan</td><td>1</td><td>0</td><td>1</td><td>1</td><td>1</td><td>1</td></tr> </table> There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die. As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up. Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco. The Next player can now choose to either # Increase the number of dice with a paco # Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra. Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11) ===Palifico=== The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated). ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza. If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid. </li></ol> 36fd19ab6020aba475beb36f7ea897f48891a5b0 1158 1157 2014-07-05T13:10:09Z Wolfkin 3936 table reformatting. wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consiquently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing with one or more dice in your hand you are the winner! ===Set up=== Each player starts with 5 dice which have the following faces: # Paco # value 2 # value 3 # value 4 # value 5 # value 6 Based on the amount of players the game begins with the following number of total dice: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 25 |- | 5 | 30 |- | 6 | 35 |} ===Round order=== All players roll their dice and check what they rolled. The first player (randomly selected) starts with an opening bid; he proclaims a die value and the amount of dice in the playfield having this exact value. He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos, unless a player is Palifico. After a bid is placed, the turn is passed on to the player on his left, this player has 2 options: # If he thinks that the last bid was wrong he can say "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players must reveal their dice. All dice that match the bid are counted.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game. ====Option 2: increasing the bid==== To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same # increase the value on the die, thus the number of dice stays the same Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts. ===Special rules=== The side of the die with the paco on is special This side counts as a joker for the number of eyes when a Dudo is called. As example: The bid on which a Dudo was called is: 9 dice with a value of 3. {| class="wikitable" style="width: 300px;" |+These dice are on the table |- ! ! colspan="6" | Dice Faces |- ! Player ! Paco ! 2 ! 3 ! 4 ! 5 ! 6 |- | Mike ||1 ||2 ||1 ||0 ||0 ||1 |- | Lucy ||0 ||3 ||1 ||1 ||0 ||0 |- | John ||3 ||0 ||1 ||0 ||0 ||1 |- | Susan ||1 ||0 ||1 ||1 ||1 ||1 |} There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die. As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up. Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco. The Next player can now choose to either # Increase the number of dice with a paco # Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra. Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11) ===Palifico=== The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated). ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza. If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid. </li></ol> 30381c5acaa568b63f6ddef100df92d61055bdec 1190 1158 2014-07-30T16:01:57Z Csq 5335 /* Set up */ wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consiquently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing with one or more dice in your hand you are the winner! ===Set up=== Each player starts with 5 dice which have the following faces: # Paco # value 2 # value 3 # value 4 # value 5 # value 6 Based on the amount of players the game begins with the following number of total dice: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} ===Round order=== All players roll their dice and check what they rolled. The first player (randomly selected) starts with an opening bid; he proclaims a die value and the amount of dice in the playfield having this exact value. He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos, unless a player is Palifico. After a bid is placed, the turn is passed on to the player on his left, this player has 2 options: # If he thinks that the last bid was wrong he can say "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players must reveal their dice. All dice that match the bid are counted.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game. ====Option 2: increasing the bid==== To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same # increase the value on the die, thus the number of dice stays the same Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts. ===Special rules=== The side of the die with the paco on is special This side counts as a joker for the number of eyes when a Dudo is called. As example: The bid on which a Dudo was called is: 9 dice with a value of 3. {| class="wikitable" style="width: 300px;" |+These dice are on the table |- ! ! colspan="6" | Dice Faces |- ! Player ! Paco ! 2 ! 3 ! 4 ! 5 ! 6 |- | Mike ||1 ||2 ||1 ||0 ||0 ||1 |- | Lucy ||0 ||3 ||1 ||1 ||0 ||0 |- | John ||3 ||0 ||1 ||0 ||0 ||1 |- | Susan ||1 ||0 ||1 ||1 ||1 ||1 |} There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die. As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up. Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco. The Next player can now choose to either # Increase the number of dice with a paco # Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra. Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11) ===Palifico=== The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated). ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza. If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid. </li></ol> 272e2c918fea7fcce1f39fdce6dfc1963c85346b Grade 0 30 1159 1083 2014-07-07T16:27:52Z Sourisdudesert 1 Undo revision 1083 by [[Special:Contributions/Da man|Da man]] ([[User talk:Da man|talk]]) wikitext text/x-wiki Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. == All grades == * '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraphim can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherubim check that Seraphim are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. * '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...) 5953d5338df3e4a588747647198989d0eede4340 Gamehelpsobek 0 166 1160 2014-07-08T01:55:28Z Wolfkin 3936 setting up. wikitext text/x-wiki #Introduction The construction of the temple dedicated to Sobek is in full swing. A whole economy has set up next to the construction site: there’s a new market, and the feluccas sailing up and down the Nile are constantly bringing goods of all sorts. Competition between merchants is naturally fierce and some are prepared to become corrupt beyond reason in order to amass glory and riches. Mainly the riches, in fact... You too are part of the local merchants’ guild and are prepared to do whatever it takes to beat your rivals... You have 3 rounds in which to acquire more money than your rivals, but try not to become too corrupt! #Game Turn On your turn, you must choose one (and only one) of the 3 actions. After which, your turn ends and it is now the player on your left’s turn to choose one of the 3 actions, and then the next, etc. ##Take A Card When you take a card, you must choose one of the four available cards and add it to your hand. By available, we mean one of the first four starting with the card nearest to the "0" space. ###Corruption Taking the first available card has no consequences since the order of arrival of the feluccas is respected. However, taking one of the other ards comes with a price... corruption! The corruption rule is simple: all the cards that you skip end up under your corruption tile. The corruption rule applies regardless of the type of card taken (goods or character). ##Play A Character Play one (and only one) character. To do this, play it face up on the discard pile (next to the deck) and apply the power shown on its papyrus. All the character powers are explained in detail on the last page of the rules. ##Play A Set A set is a group of goods cards of the same type To play a set, you must place at least 3 goods cards face up in front of you. (You can, of course, play more.) `A few notes`: A set can include one or more amulets (joker). Each character, being associated with a goods type, can therefore be included in a set of that same goods type. Note, though, that when a character is played as part of a set, its power is ignored! It is possible to add cards to a set that has already been played (in order to earn more points during scoring), but the same rule still applies: you must add a minimum of 3 new cards. ###Event Tokens As long as at least 1 of the 5 tokens hasn’t yet been played, playing a set immediately triggers an event. When you play a set, take all the remaining tokens, choose one, and immediately apply its effect. The token is then discarded. In order to prevent another player from taking advantage of a token, you may choose a token whose effect cannot be applied or which has no effect on you. In that case, you simply discard it. All the tokens are explained on the last page of the rules. 1a902ef613b406aa59374518b59baa0d740bd812 1161 1160 2014-07-08T01:57:58Z Wolfkin 3936 formatting wikitext text/x-wiki =Introduction= The construction of the temple dedicated to Sobek is in full swing. A whole economy has set up next to the construction site: there’s a new market, and the feluccas sailing up and down the Nile are constantly bringing goods of all sorts. Competition between merchants is naturally fierce and some are prepared to become corrupt beyond reason in order to amass glory and riches. Mainly the riches, in fact... You too are part of the local merchants’ guild and are prepared to do whatever it takes to beat your rivals... You have 3 rounds in which to acquire more money than your rivals, but try not to become too corrupt! =Game Turn= On your turn, you must choose one (and only one) of the 3 actions. After which, your turn ends and it is now the player on your left’s turn to choose one of the 3 actions, and then the next, etc. ==Take A Card== When you take a card, you must choose one of the four available cards and add it to your hand. By available, we mean one of the first four starting with the card nearest to the "0" space. ===Corruption=== Taking the first available card has no consequences since the order of arrival of the feluccas is respected. However, taking one of the other ards comes with a price... corruption! The corruption rule is simple: all the cards that you skip end up under your corruption tile. The corruption rule applies regardless of the type of card taken (goods or character). ==Play A Character== Play one (and only one) character. To do this, play it face up on the discard pile (next to the deck) and apply the power shown on its papyrus. All the character powers are explained in detail on the last page of the rules. ==Play A Set== A set is a group of goods cards of the same type To play a set, you must place at least 3 goods cards face up in front of you. (You can, of course, play more.) `A few notes`: A set can include one or more amulets (joker). Each character, being associated with a goods type, can therefore be included in a set of that same goods type. Note, though, that when a character is played as part of a set, its power is ignored! It is possible to add cards to a set that has already been played (in order to earn more points during scoring), but the same rule still applies: you must add a minimum of 3 new cards. ===Event Tokens=== As long as at least 1 of the 5 tokens hasn’t yet been played, playing a set immediately triggers an event. When you play a set, take all the remaining tokens, choose one, and immediately apply its effect. The token is then discarded. In order to prevent another player from taking advantage of a token, you may choose a token whose effect cannot be applied or which has no effect on you. In that case, you simply discard it. All the tokens are explained on the last page of the rules. ecd81e81bca8ba535e0019c9d5388f22cabb22f5 1184 1161 2014-07-21T14:01:19Z Drstuey 3099 complete rewrite, removing the text copied from the rules and summarising instead, plus adding more wikitext text/x-wiki ==Theme== Players are merchants trading in the economy that has grown up next to the construction site of the temple dedicated to Sobek. There’s a market, and the feluccas sailing up and down the Nile are bringing goods of all sorts. You have 3 rounds in which to acquire more money than your rivals, but try not to become too corrupt. ==Game turns and actions== On your turn you must choose one of the 3 actions. Then play passes to the player on your left. The actions are: * '''Take a card from the marketplace and add it to your hand''' : Only the first four cards (starting from the left) are available. Taking the first available card has no consequences since the order of arrival of the feluccas is respected. However, taking one of the other cards causes corruption. All the cards that you skip end up in your corruption pile. * '''Play a character card and apply its power''' * '''Play a set''' : A set is a group of at least three goods cards of the same type. A set can include one or more amulets which act as wild cards (jokers). A set can also include characters - each character is associated with a goods type; this is shown on the card. When a character is played as part of a set, its power is ignored. : It is possible to add cards to a set that has already been played (in order to earn more points during scoring), but the same rule still applies: you must add a minimum of 3 new cards. : When a set is played an event are triggered (provided at least 1 of the 5 event tokens remains). The player who played the set chooses an event from the remaining tokens and immediately applies its effect. The token is then discarded. ==Event tokens== There are 12 event tokens with 5 randomly selected for each round: * 4 x Guild - (one of each of snake, reed, ankh, scorpion). On the scoring track, move your scoring marker forward to the next space of that symbol and move an opponent's scoring marker back to the next space of that symbol. * 2 x Flood - Take another turn * 2 x Curse - Add a curse token to another player's corruption pile; it counts as 2 cards in that player's pile. * 2 x Prosperity - add the token to one of your fish, cattle or wheat sets, thus increasing the score of this set. * 1 x Embalming - return all the cards from your corruption pile to your hand * 1 x Deceit - Score the number of cards in your corruption pile ==Character cards== * 1 x Queen Sobek Neferou - draw 3 cards and add them to your hand. * 2 x High Priest/Priestess - discard all the cards of one goods type from your corruption pile. Characters of that goods type can be discarded. Amulets (wild cards) cannot be discarded. * 2 x Scribe - your opponents reduce their hands down to 6 cards; the remainder are added to their corruption pile. * 1 x Vizir - add a card of your choice to your hand from an opponent's corruption pile. * 1 x Courtesan - add 1 or 2 cards from your hand to an existing played set. * 1 x Thief - steal a card from an opponent. You can see the different coloured backs of the card so you know which type of card you are stealing. ==End of the round== The round ends and is scored when the last card is taken from the marketplace. Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand. You cannot play character cards; you cannot add to existing sets. All cards remaining in the players hand are added to their corruption pile. Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs. Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols. == Game end == The game ends after 3 rounds. The game can end early if one player gets more than 100 points. 8d6b03e7700445ee6c02d79ec271b107b1ed9c89 1185 1184 2014-07-21T14:16:51Z Drstuey 3099 add goods cards wikitext text/x-wiki ==Theme== Players are merchants trading in the economy that has grown up next to the construction site of the temple dedicated to Sobek. There’s a market, and the feluccas sailing up and down the Nile are bringing goods of all sorts. You have 3 rounds in which to acquire more money than your rivals, but try not to become too corrupt. ==Game turns and actions== On your turn you must choose one of the 3 actions. Then play passes to the player on your left. The actions are: * '''Take a card from the marketplace and add it to your hand''' : Only the first four cards (starting from the left) are available. Taking the first available card has no consequences since the order of arrival of the feluccas is respected. However, taking one of the other cards causes corruption. All the cards that you skip end up in your corruption pile. * '''Play a character card and apply its power''' : See below for powers. * '''Play a set''' : A set is a group of at least three goods cards of the same type. A set can include one or more amulets which act as wild cards (jokers). A set can also include characters - each character is associated with a goods type; this is shown on the card. When a character is played as part of a set, its power is ignored. : It is possible to add cards to a set that has already been played (in order to earn more points during scoring), but the same rule still applies: you must add a minimum of 3 new cards. : When a set is played an event are triggered (provided at least 1 of the 5 event tokens remains). The player who played the set chooses an event from the remaining tokens and immediately applies its effect. The token is then discarded. ==Event tokens== There are 12 event tokens with 5 randomly selected for each round: * 4 x Guild - (one of each of snake, reed, ankh, scorpion). On the scoring track, move your scoring marker forward to the next space of that symbol and move an opponent's scoring marker back to the next space of that symbol. * 2 x Flood - Take another turn * 2 x Curse - Add a curse token to another player's corruption pile; it counts as 2 cards in that player's pile. * 2 x Prosperity - add the token to one of your fish, cattle or wheat sets, thus increasing the score of this set. * 1 x Embalming - return all the cards from your corruption pile to your hand * 1 x Deceit - Score the number of cards in your corruption pile ==Character cards== * 1 x Queen Sobek Neferou - draw 3 cards and add them to your hand. * 2 x High Priest/Priestess - discard all the cards of one goods type from your corruption pile. Characters of that goods type can be discarded. Amulets (wild cards) cannot be discarded. * 2 x Scribe - your opponents reduce their hands down to 6 cards; the remainder are added to their corruption pile. * 1 x Vizir - add a card of your choice to your hand from an opponent's corruption pile. * 1 x Courtesan - add 1 or 2 cards from your hand to an existing played set. * 1 x Thief - steal a card from an opponent. You can see the different coloured backs of the card so you know which type of card you are stealing. ==Goods cards== There are 54 goods cards in total: 6 x Ivory 7 x Ebony 7 x Marble 9 x Cattle 10 x Fish 10 x Wheat 5 x Amulet Nine of the cards have a different coloured back; the player's starting hand is dealt from these leaving 45 cards which are shuffled with the character cards to form the deck. In a two player game 9 cards are removed at random so there will be only 5 goods deliveries not 6 as normal. ==End of the round== The round ends and is scored when the last card is taken from the marketplace. Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand. You cannot play character cards; you cannot add to existing sets. All cards remaining in the players hand are added to their corruption pile. Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs. Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols. == Game end == The game ends after 3 rounds. The game can end early if one player gets more than 100 points. 873776f4d7f57963268c504993e6a6d219b7a700 1186 1185 2014-07-22T11:37:02Z Drstuey 3099 /* Goods cards */ wikitext text/x-wiki ==Theme== Players are merchants trading in the economy that has grown up next to the construction site of the temple dedicated to Sobek. There’s a market, and the feluccas sailing up and down the Nile are bringing goods of all sorts. You have 3 rounds in which to acquire more money than your rivals, but try not to become too corrupt. ==Game turns and actions== On your turn you must choose one of the 3 actions. Then play passes to the player on your left. The actions are: * '''Take a card from the marketplace and add it to your hand''' : Only the first four cards (starting from the left) are available. Taking the first available card has no consequences since the order of arrival of the feluccas is respected. However, taking one of the other cards causes corruption. All the cards that you skip end up in your corruption pile. * '''Play a character card and apply its power''' : See below for powers. * '''Play a set''' : A set is a group of at least three goods cards of the same type. A set can include one or more amulets which act as wild cards (jokers). A set can also include characters - each character is associated with a goods type; this is shown on the card. When a character is played as part of a set, its power is ignored. : It is possible to add cards to a set that has already been played (in order to earn more points during scoring), but the same rule still applies: you must add a minimum of 3 new cards. : When a set is played an event are triggered (provided at least 1 of the 5 event tokens remains). The player who played the set chooses an event from the remaining tokens and immediately applies its effect. The token is then discarded. ==Event tokens== There are 12 event tokens with 5 randomly selected for each round: * 4 x Guild - (one of each of snake, reed, ankh, scorpion). On the scoring track, move your scoring marker forward to the next space of that symbol and move an opponent's scoring marker back to the next space of that symbol. * 2 x Flood - Take another turn * 2 x Curse - Add a curse token to another player's corruption pile; it counts as 2 cards in that player's pile. * 2 x Prosperity - add the token to one of your fish, cattle or wheat sets, thus increasing the score of this set. * 1 x Embalming - return all the cards from your corruption pile to your hand * 1 x Deceit - Score the number of cards in your corruption pile ==Character cards== * 1 x Queen Sobek Neferou - draw 3 cards and add them to your hand. * 2 x High Priest/Priestess - discard all the cards of one goods type from your corruption pile. Characters of that goods type can be discarded. Amulets (wild cards) cannot be discarded. * 2 x Scribe - your opponents reduce their hands down to 6 cards; the remainder are added to their corruption pile. * 1 x Vizir - add a card of your choice to your hand from an opponent's corruption pile. * 1 x Courtesan - add 1 or 2 cards from your hand to an existing played set. * 1 x Thief - steal a card from an opponent. You can see the different coloured backs of the card so you know which type of card you are stealing. ==Goods cards== There are 54 goods cards in total: :6 x Ivory :7 x Ebony :7 x Marble :9 x Cattle :10 x Fish :10 x Wheat :5 x Amulet Nine of the cards have a different coloured back; the player's starting hand is dealt from these leaving 45 cards which are shuffled with the character cards to form the deck. In a two player game 9 cards are removed at random so there will be only 5 goods deliveries not 6 as normal. ==End of the round== The round ends and is scored when the last card is taken from the marketplace. Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand. You cannot play character cards; you cannot add to existing sets. All cards remaining in the players hand are added to their corruption pile. Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs. Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols. == Game end == The game ends after 3 rounds. The game can end early if one player gets more than 100 points. 0f4f9d8bee63407b55ed5d3d4a0fc2e9a1d93085 1187 1186 2014-07-22T11:37:50Z Drstuey 3099 /* Theme */ wikitext text/x-wiki ==Theme== Players are merchants trading in the economy that has grown up next to the construction site of the temple dedicated to Sobek. There's a market, and the feluccas sailing up and down the Nile are bringing goods of all sorts. You have 3 rounds in which to acquire more money than your rivals, but try not to become too corrupt. ==Game turns and actions== On your turn you must choose one of the 3 actions. Then play passes to the player on your left. The actions are: * '''Take a card from the marketplace and add it to your hand''' : Only the first four cards (starting from the left) are available. Taking the first available card has no consequences since the order of arrival of the feluccas is respected. However, taking one of the other cards causes corruption. All the cards that you skip end up in your corruption pile. * '''Play a character card and apply its power''' : See below for powers. * '''Play a set''' : A set is a group of at least three goods cards of the same type. A set can include one or more amulets which act as wild cards (jokers). A set can also include characters - each character is associated with a goods type; this is shown on the card. When a character is played as part of a set, its power is ignored. : It is possible to add cards to a set that has already been played (in order to earn more points during scoring), but the same rule still applies: you must add a minimum of 3 new cards. : When a set is played an event are triggered (provided at least 1 of the 5 event tokens remains). The player who played the set chooses an event from the remaining tokens and immediately applies its effect. The token is then discarded. ==Event tokens== There are 12 event tokens with 5 randomly selected for each round: * 4 x Guild - (one of each of snake, reed, ankh, scorpion). On the scoring track, move your scoring marker forward to the next space of that symbol and move an opponent's scoring marker back to the next space of that symbol. * 2 x Flood - Take another turn * 2 x Curse - Add a curse token to another player's corruption pile; it counts as 2 cards in that player's pile. * 2 x Prosperity - add the token to one of your fish, cattle or wheat sets, thus increasing the score of this set. * 1 x Embalming - return all the cards from your corruption pile to your hand * 1 x Deceit - Score the number of cards in your corruption pile ==Character cards== * 1 x Queen Sobek Neferou - draw 3 cards and add them to your hand. * 2 x High Priest/Priestess - discard all the cards of one goods type from your corruption pile. Characters of that goods type can be discarded. Amulets (wild cards) cannot be discarded. * 2 x Scribe - your opponents reduce their hands down to 6 cards; the remainder are added to their corruption pile. * 1 x Vizir - add a card of your choice to your hand from an opponent's corruption pile. * 1 x Courtesan - add 1 or 2 cards from your hand to an existing played set. * 1 x Thief - steal a card from an opponent. You can see the different coloured backs of the card so you know which type of card you are stealing. ==Goods cards== There are 54 goods cards in total: :6 x Ivory :7 x Ebony :7 x Marble :9 x Cattle :10 x Fish :10 x Wheat :5 x Amulet Nine of the cards have a different coloured back; the player's starting hand is dealt from these leaving 45 cards which are shuffled with the character cards to form the deck. In a two player game 9 cards are removed at random so there will be only 5 goods deliveries not 6 as normal. ==End of the round== The round ends and is scored when the last card is taken from the marketplace. Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand. You cannot play character cards; you cannot add to existing sets. All cards remaining in the players hand are added to their corruption pile. Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs. Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols. == Game end == The game ends after 3 rounds. The game can end early if one player gets more than 100 points. 30e7c1e67b298ba7b4c34925c31df0ad74a8049e Gamehelphive 0 167 1162 2014-07-09T02:55:38Z Rainn 5818 Created page with "Each turn, you may either place an insect or move an insect. All insects in play must be contiguous at all times. The first player's Queen Bee to be surrounded on all sides l..." wikitext text/x-wiki Each turn, you may either place an insect or move an insect. All insects in play must be contiguous at all times. The first player's Queen Bee to be surrounded on all sides loses. Movement rules: * Queen Bee: Can only move one space * c10f3c67e3a8da586533c957f7d0c99c04c2cb71 1163 1162 2014-07-09T03:35:38Z Rainn 5818 wikitext text/x-wiki Each turn, you may either place an insect or move an insect. All insects in play must be contiguous at all times. The first player's Queen Bee to be surrounded on all sides loses. Movement rules: * Queen Bee: Can only move one space * Beetle: Only one space, but it can move on top of another insect * Spider: 3 spaces in a straight line * Grasshopper: Moves to the next open space in a straight line * Soldier Ant: It can move unlimited times along borders This is just a brief summary of movement rules. This has a comprehensive overview of movement rules: http://boardgamegeek.com/thread/371756/hive-detailed-review 987a1958204c98e11d91a5360659d498357bf740 1164 1163 2014-07-09T03:48:20Z Rainn 5818 wikitext text/x-wiki Each turn, you may either place an insect or move an insect. All insects in play must be contiguous at all times. The first player's Queen Bee to be surrounded on all sides loses. You must place your Queen be by your fourth turn. Movement rules: * Queen Bee: Can only move one space * Beetle: Only one space, but it can move on top of another insect * Spider: 3 spaces in a straight line * Grasshopper: Moves to the next open space in a straight line * Soldier Ant: It can move unlimited times along borders This is just a brief summary of movement rules. This has a comprehensive overview of movement rules: http://boardgamegeek.com/thread/371756/hive-detailed-review 62d0aeacced1b915f73826e493449e2021632d21 Faq 0 3 1165 1134 2014-07-10T21:41:21Z Jest phulin 3510 Expanded the answer under "turn-based" play. Also fixed a missing double quote, and a misspelling. wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena, your opponents are connected to the game platform all along the game, and they can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used to differentiate against "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move, you are notified that it is your turn (via email or visiting the site). You then go to your game, take your turn, and the process repeats for another player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his allotted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. 0fd6cffd7d9330120d8519b19377e164814026d9 Gamehelpcoloretto 0 33 1166 705 2014-07-14T13:40:59Z Zlatovrana 6098 wikitext text/x-wiki There are several colors of chameleons (depending on the number of players) and 2 kinds of special cards: Joker and +2. At the beginning each players gets randomly 1 card with a chameleon of different color than any other player. On their turn players can : 1. draw a new card and put it in one of the rows (there are as many rows as players) 2. take a row of cards When a player takes a row his or her turn is skipped until all players have taken a row. Then a new round starts, and players can again fill rows with cards. The game ends at the end of a round during which the 'Last round' card is drawn. The player who drew the 'Last round' card puts it away and draws another card. Same colored chameleons are put into sets. The more cards of that color you have the more points it is worth. Only 3 sets bring you positive points, while every other set brings you negative points. You get to choose at the end of the game which sets will be positive (the bga does that for you). The Joker (chameleon with many-colored background) can be put into any set at the end of the game. +2 always brings you 2 positive points at the end of the game.It is never a part of a set. The player with the most points wins. c440cd17b5b5aa9c334194d1f39c5453a42d920d Gamehelpthroughtheages 0 168 1167 2014-07-18T02:44:41Z Rainn 5818 Created page with "Turn structure: * Play a political card (if you have one) * Spend your ''military actions'' to build military units, and ''civil actions'' to: ** pick cards from the card rows..." wikitext text/x-wiki Turn structure: * Play a political card (if you have one) * Spend your ''military actions'' to build military units, and ''civil actions'' to: ** pick cards from the card rows ** play cards to your tableau ** increase your population ** build/upgrade farms, mines, or urban buildings Symbols and counters: * '''yellow''' counters represent your population. They can be in one of three places: ** on your farms, mines, urban buildings, or military units (representing workers) ** your available population ** your "population bank" 444adf5b9707a0e8cf7aa41c63055b3d89137622 1168 1167 2014-07-18T02:53:55Z Rainn 5818 wikitext text/x-wiki Turn structure: * Play a political card (if you have one) * Spend your ''military actions'' to build military units, and ''civil actions'' to: ** pick cards from the card rows ** play cards to your tableau ** increase your population ** build/upgrade farms, mines, or urban buildings Symbols and counters: * '''yellow''' counters represent your population. They can be in one of three places: ** on your farms, mines, urban buildings, or military units (representing workers) ** on your available population, which are available to place on your cards ** on your "yellow bank" -- when this is empty, you can no longer increase your available population * '''blue''' counters represent food or resources. They can be in two places: ** on your farms or mines ** on your "blue bank" -- when this is empty, you can no longer produce * '''white''' circles (on some cards) represent civil actions * '''red''' circles (on some cards) represent military actions c1ff953ddca58a8a55a3f4da75c92308a1aa124d 1169 1168 2014-07-18T02:56:30Z Rainn 5818 wikitext text/x-wiki Turn structure: * Play a political card (if you have one) * Spend your ''military actions'' to build military units, and ''civil actions'' to: ** pick cards from the card rows (if you have room in your hand) ** play cards to your tableau ** increase your population ** build/upgrade farms, mines, or urban buildings Yellow counters represent your population. They can be in one of three places: * on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers) * on your available population, which are available to place on your cards * on your "yellow bank" -- when this is empty, you can no longer increase your available population Blue counters represent food or resources. They can be in two places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce 3ec12510138b87117c4b4710a14712712bfc8b96 1170 1169 2014-07-18T03:04:29Z Rainn 5818 wikitext text/x-wiki Turn structure: 1. Play a political card (if you have one) 2. Spend your ''military actions'' to build military units, and ''civil actions'' to: * pick cards from the card rows (if you have room in your hand) * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings Yellow counters represent your population. They can be in one of three places: * on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers) * on your available population, which are available to place on your cards * on your "yellow bank" -- when this is empty, you can no longer increase your available population Blue counters represent food or resources. They can be in two places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce Building or upgrading farms will help you increase your population. Building or upgrading mines will help you build more farms, mines, urban buildings, or military. Producing more ''science'' (light bulbs) will let you play technologies for better farms, mines, urban buildings, or military. When your population grows, you will need to produce more ''happiness'' or your workers will stop working. Producing ''culture'' will earn you victory points. Producing more ''military strength'' will protect you from raids or wars. There are 3 versions: * ''simple'' plays through Age I * ''advanced'' plays through Age II, and introduces colonies, raids, unhappiness, and corruption * ''complete'' plays through Age III, and introduces wars d57e655edd2555f710f45060b0300fc67ace524f 1171 1170 2014-07-18T03:20:16Z Rainn 5818 wikitext text/x-wiki Turn structure: 1. Play a political card (if you have one) 2. Spend your ''military actions'' to build military units, and ''civil actions'' to: * pick cards from the card rows (if you have room in your hand) * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings Yellow counters represent your population. They can be in one of three places: * on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers) * on your available population, which are available to place on your cards * on your "yellow bank" -- when this is empty, you can no longer increase your available population Blue counters represent food or resources. They can be in two places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce Building up your civilisation: * Building or upgrading farms will help you increase your population. * Building or upgrading mines will help you build more farms, mines, urban buildings, or military. * Producing more ''science'' (light bulbs) will let you play technologies for better farms, mines, urban buildings, or military. * When your population grows, you will need to produce more ''happiness'' or your workers will stop working. * Producing ''culture'' will earn you victory points. * Producing more ''military strength'' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''simple'' plays through Age I * ''advanced'' plays through Age II, and introduces colonies, raids, unhappiness, and corruption * ''complete'' plays through Age III, and introduces wars 157642326b5576dee833967d04fdc9fab0f7ca09 1172 1171 2014-07-18T03:22:22Z Rainn 5818 wikitext text/x-wiki During your turn, you may spend your ''civil actions'' to: * pick cards from the card rows (if you have room in your hand) * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * but building/upgrading military units uses your ''military actions'' Yellow counters represent your population. They can be in one of three places: * on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers) * on your available population, which are available to place on your cards * on your "yellow bank" -- when this is empty, you can no longer increase your available population Blue counters represent food or resources. They can be in two places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce Building up your civilisation: * Building or upgrading farms will help you increase your population. * Building or upgrading mines will help you build more farms, mines, urban buildings, or military. * Producing more ''science'' (light bulbs) will let you play technologies for better farms, mines, urban buildings, or military. * When your population grows, you will need to produce more ''happiness'' or your workers will stop working. * Producing ''culture'' will earn you victory points. * Producing more ''military strength'' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''simple'' plays through Age I * ''advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''complete'' plays through Age III, and introduces wars e486e3fac3720372a1217da8821347534e6d0c06 1173 1172 2014-07-18T03:22:56Z Rainn 5818 wikitext text/x-wiki During your turn, you may spend your '''civil actions''' to: * pick cards from the card rows (if you have room in your hand) * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * but building/upgrading military units uses your '''military actions''' '''Yellow counters''' represent your population. They can be in one of three places: * on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers) * on your available population, which are available to place on your cards * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in two places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce Building up your civilisation: * Building or upgrading farms will help you increase your population. * Building or upgrading mines will help you build more farms, mines, urban buildings, or military. * Producing more ''science'' (light bulbs) will let you play technologies for better farms, mines, urban buildings, or military. * When your population grows, you will need to produce more ''happiness'' or your workers will stop working. * Producing ''culture'' will earn you victory points. * Producing more ''military strength'' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars e7a3197b62b75f29713c518279f456e960c7fd15 1174 1173 2014-07-18T03:49:14Z Rainn 5818 wikitext text/x-wiki During your turn, you may spend your '''civil actions''' to: * pick cards from the card rows (if you have room in your hand) * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * but building/upgrading military units uses your '''military actions''' '''Yellow counters''' represent your population. They can be in one of three places: * on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers) * on your available population, which are available to place on your cards * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in two places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce Building up your civilisation: * Building or upgrading farms will help you increase your population. * Building or upgrading mines will help you build more farms, mines, urban buildings, or military. * Producing more '''science''' (light bulbs) will let you play technologies for better farms, mines, urban buildings, or military. * When your population grows, you will need to produce more '''happiness''' or your workers will stop working. * Producing '''culture''' will earn you victory points. * Producing more '''military strength''' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars 99edd3832c3b0f626ef487087673979df4d27f2b 1175 1174 2014-07-18T04:04:00Z Rainn 5818 wikitext text/x-wiki During your turn, you may spend your '''civil actions''' to: * pick cards from the card rows (if you have room in your hand) * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * but building/upgrading military units uses your '''military actions''' '''Yellow counters''' represent your population. They can be in one of three places: * on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers) * on your available population, which are available to place on your cards * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in two places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce Building up your civilisation: * '''Food''' lets you move workers from your yellow bank to your available worker pool. * '''Resources''' let you move workers from your available worker pool to a card on your tableau. * '''Science'' (light bulbs) lets you move cards from your hand to your tableau. * When your population grows, you will need to produce more '''happiness''' or your workers will stop working. * Producing '''culture''' will earn you victory points. * Producing more '''military strength''' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars 88888c63ee8358a776fcef0245588af116fe7fd3 1176 1175 2014-07-18T04:04:19Z Rainn 5818 wikitext text/x-wiki During your turn, you may spend your '''civil actions''' to: * pick cards from the card rows (if you have room in your hand) * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * but building/upgrading military units uses your '''military actions''' '''Yellow counters''' represent your population. They can be in one of three places: * on your farms, mines, urban buildings (grey-backed cards, such as ''philosophy''), or military units (representing workers) * on your available population, which are available to place on your cards * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in two places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce Building up your civilisation: * '''Food''' lets you move workers from your yellow bank to your available worker pool. * '''Resources''' let you move workers from your available worker pool to a card on your tableau. * '''Science''' (light bulbs) lets you move cards from your hand to your tableau. * When your population grows, you will need to produce more '''happiness''' or your workers will stop working. * Producing '''culture''' will earn you victory points. * Producing more '''military strength''' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars 9b829079a84c97e6facc85dcff01bdeb8d0afe63 1177 1176 2014-07-18T04:05:29Z Rainn 5818 wikitext text/x-wiki During your turn, you may spend your '''civil actions''' to: * pick cards from the card rows (if you have room in your hand) * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * but building/upgrading military units uses your '''military actions''' '''Yellow counters''' represent your population. They can be in one of three places: * on the cards on your tableau * on your available worker pool * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in two places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce food or resources Building up your civilisation: * '''Food''' lets you move workers from your yellow bank to your available worker pool. * '''Resources''' let you move workers from your available worker pool to a card on your tableau. * '''Science''' (light bulbs) lets you move cards from your hand to your tableau. * When your population grows, you will need to produce more '''happiness''' or your workers will stop working. * Producing '''culture''' will earn you victory points. * Producing more '''military strength''' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars c81481d2450cf4d42b4d79e8a9629461a81e5aea 1178 1177 2014-07-18T04:06:08Z Rainn 5818 wikitext text/x-wiki During your turn, you may spend your '''actions points''' to: * pick cards from the card rows (if you have room in your hand) * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * build/upgrade military units '''Yellow counters''' represent your population. They can be in one of three places: * on the cards on your tableau * on your available worker pool * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in two places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce food or resources Building up your civilisation: * '''Food''' lets you move workers from your yellow bank to your available worker pool. * '''Resources''' let you move workers from your available worker pool to a card on your tableau. * '''Science''' (light bulbs) lets you move cards from your hand to your tableau. * When your population grows, you will need to produce more '''happiness''' or your workers will stop working. * Producing '''culture''' will earn you victory points. * Producing more '''military strength''' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars 484660cf22ac79264faa9e91bdd7256ebe331837 1191 1178 2014-08-05T06:18:37Z Alcandor 6238 wikitext text/x-wiki During your turn, you may spend your '''actions points''' to: * pick cards from the card rows (if you have room in your hand) * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * build/upgrade military units '''Yellow counters''' represent your population. They can be in one of three places: * on the cards on your tableau * on your available worker pool * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in two places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce food or resources Building up your civilisation: * '''Food''' lets you move workers from your yellow bank to your available worker pool. * '''Resources''' let you move workers from your available worker pool to a card on your tableau. * '''Science''' (light bulbs) lets you move cards from your hand to your tableau. * When your population grows, you will need to produce more '''happiness''' or your workers will stop working. * Producing '''culture''' will earn you victory points. * Producing more '''military strength''' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars Points scored at end game: * 2 culture scored per 1 Strength (military) * 1 culture scored per 1 Science Rating (per turn) * 2 culture scored per Happy Face * 2 culture scored per level 1 technology in play * 1 culture scored per food or resource production per turn 67fb0b17f81db2d673b71a29b39f4a3a76a20d77 Gamehelptargi 0 169 1179 2014-07-18T05:23:43Z Rainn 5818 Created page with "Each round of play has the following stages: # Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column ..." wikitext text/x-wiki Each round of play has the following stages: # Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column as your opponent's Targi. # Place 1 or 2 "tribal markers" in the middle of the game board at the intersection of the rows/columns of your targi. # You may may then activate the cards under each of your pieces. These cards may give you more goods, or they may let you spend your goods to purchase special cards to place in your personal tableau. 167801bdf5386c5abc0261fa03846952fd556bb5 1180 1179 2014-07-18T05:27:16Z Rainn 5818 wikitext text/x-wiki Each round of play has the following stages: # Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column as your opponent's Targi. # Place 1 or 2 "tribal markers" in the middle of the game board at the intersection of the rows/columns of your targi. # You may may then activate the cards under each of your pieces. These cards may give you more goods, or they may let you spend your goods to purchase special cards to place in your personal tableau. You may only hold 3 gold and 10 goods total between rounds. 6a60c8ce5619e74e6f8336596b4d492c6d355de0 1181 1180 2014-07-18T06:29:50Z Rainn 5818 wikitext text/x-wiki Each round of play has the following stages: # Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column as your opponent's Targi. # Place 1 or 2 "tribal markers" in the middle of the game board at the intersection of the rows/columns of your targi. # You may may then activate the cards under each of your pieces. These cards may give you more goods, or they may let you spend your goods to purchase special cards to place in your personal tableau. You may only hold 3 gold and 10 goods total between rounds. In addition to the victory points earned during the game and from special card abilities, you also get: * 4 victory points for a building a row of identical cards in your tableau, and * 2 victory points for a row of unique cards 54704b1066c0fbc0e49139892c7cb8efa0c61b01 1182 1181 2014-07-18T06:45:12Z Rainn 5818 wikitext text/x-wiki Each round of play has the following stages: # Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column as your opponent's Targi. # Place 1 or 2 "tribal markers" in the middle of the game board at the intersection of the rows/columns of your targi. # You may may then activate the cards under each of your pieces. These cards may give you more goods, or they may let you spend your goods to purchase special cards to place in your personal tableau. You may only hold 3 gold and 10 goods total between rounds. The game ends when a player has filled their tableau, or when the robber has completed one jog around the map. In addition to the victory points earned during the game and from special card abilities, you also get: * 4 victory points for a building a row of identical cards in your tableau, and * 2 victory points for a row of unique cards 154f31063c025aa504be5c1803848d2ab572d886 1183 1182 2014-07-18T06:47:01Z Rainn 5818 wikitext text/x-wiki Each round of play has the following stages: # Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column as your opponent's Targi. # Place 1 or 2 "tribal markers" in the middle of the game board at the intersection of the rows/columns of your targi. # You may may then activate the cards under each of your pieces. These cards may give you more goods, or they may let you spend your goods to purchase special cards to place in your personal tableau. You may only hold 3 gold and 10 goods total between rounds. The game ends when a player has filled their tableau, or when the robber has completed one jog around the map. In addition to the victory points earned during the game and from special card abilities, you also get: * 4 victory points for a building a row of identical cards in your tableau, and * 2 victory points for a row of all different cards b15941ecf92b5d3fb5552e1877d6d7d78db350cf Stock 0 97 1188 1113 2014-07-27T12:28:50Z Sourisdudesert 1 /* Complete stock component reference */ wikitext text/x-wiki "Stock" is a javascript component that you can use on your game interface to display a set of elements of the same size that need to be arranged in one or several lines. Stock is very flexible and is the most used component in BGA games. Stock is used for example: * To display set of cards, typically hands (ex: in Hearts, Seasons, The Boss, Race for the Galaxy, ...). * To display items in player panels (ex: Takenoko, Amyitis, ...) * ... in many other situations. For example, black dice and cubes on cards in Troyes are displayed with stock components. Using stock: * Your items are arranged nicely and sorted by type. * When adding (or removing) items to the set. All items slide smoothly to their new position in the set to host the new one. * Select/unselect items is a built-in functionnality. * You don't have to care about inserting/removing HTML piece of code: the entire life of the stock is managed by the component. == Using stock: a simple example == Let's have a look on how the stock is used in game "Hearts" to display a hand of standard cards. At first, don't forget to add "ebg/stock" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <==== HERE ], </pre> The stock is initialized in Javascript "setup" method like this: <pre> // Player hand this.playerHand = new ebg.stock(); this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight ); </pre> Explanations: * We create a new stock object for the player hand. * As parameters of the "create" method, we provide the width/height of an item (=a card), and the container div "myhand" - which is a simple void "div" element defines in our HTML template (.tpl). Then, we must tell the stock what are the items it is going to display during its life: the 52 cards of a standard card game. Of course, we did not create 52 different images, but create a "CSS sprite" image named "cards.jpg" with all the cards arranged in 4 rows and 13 columns. Here's how we tell stock what are the items type to display: <pre> // Explain there are 13 images per row in the CSS sprite image this.playerHand.image_items_per_row = 13; // Create cards types: for( var color=1;color<=4;color++ ) { for( var value=2;value<=14;value++ ) { // Build card type id var card_type_id = this.getCardUniqueId( color, value ); this.playerHand.addItemType( card_type_id, card_type_id, g_gamethemeurl+'img/cards.jpg', card_type_id ); } } </pre> Explanations: * At first, we tell the stock component that our CSS sprite contains 13 items per row. This way, it can find the correct image for each card type id. * Then for the 4x13 cards, we call "addItemType" method that create the type. The arguments are the type id, the weight of the card (for sorting purpose), the URL of our CSS sprite, and the position of our card image in the CSS sprite. Note: in this specific example we need to generate a unique ID for each type of card based on its color and value. This is the only purpose of "getCardUniqueId". From now, if we need to add - for example - the 5 of Heart to player's hand, we can do this. this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ) ); In reality, cards have some IDs, which are useful to manipulate them. This is the reason we are using "addToStockWithId" instead: this.playerHand.addToStock( this.getCardUniqueId( 2 /* 2=hearts */, 5 ), my_card_id ); If afterwards we want to remove this card from the stock: this.playerHand.removeFromStockById( my_card_id ); == Complete stock component reference == '''create( page, container_div, item_width, item_height ):''' With create, you create a new stock component. Parameters: * page: the container page. Usually: "this". * container_div: the container "div" element (a void div element in your template, with an id). * a stock item width and height, in pixels. (See "Hearts" example above). '''count():''' Return the total number of items in the stock right now. '''addItemType( type, weight, image, image_position ):''' Define a new type of item to the stock. This is mandatory to define a new item type before adding it to the stock. Example: if you want to have a stock control that can contains cubes of 3 different colors, you must add 3 item types (one for each color). Parameters: * type: ID of the type to add. You can choose any positive integer. All item types must have distinct IDs. * weight: weight of items of this type. Weight value is used to sort items of the stock during the display. Note that you can specify the same weight for all items (in this case they are not sorted and their order might change randomly at any time). * image: URL of item image. Most of the time, you will use a CSS sprite for stock item, so you have to specify CSS sprite image here. Be careful: you must specify the image url as this: <pre> g_gamethemeurl+'img/yourimage.png' </pre> * image_position: if "image" specify the URL of a CSS sprite, you must specify the position of the item image in this CSS sprite. For example, if you have a CSS sprite with 3 cubes with a size of 20x20 pixels each (so your CSS image has for example a size of 20x60 or 60x20), you specify "0" for the first cube image, 1 for the second, 2 for the third. Important: there are more than one line of items in your CSS sprite, you must specify how many items per line you have in your CSS sprite like this: <pre> // Specify that there is 10 image items per row in images used in "myStockObject" control. this.myStockObject.image_items_per_row = 10; </pre> '''addToStock( type, from )''' Add an item to the stock, with the specified type. To make your life easy, in most of the case we suggest you to use "addToStockWithId" in order to give an ID to the item added. "addToStock" is perfect when you are using a stock controls with items that are generic game material that does not need to be addressed individually (ex: a bunch of money tokens). Parameters: * type: ID of the item type to use (as specified in "addItemType") * from: OPTIONNAL: if you specify a HTML item here, the item will appear on this item and will be slided to its position on the stock item. Example: <pre> // Add a money token to the "player money" stock. // The money token will appear on "player_id" player panel and will move to its position. this.playerMoney.addToStock( MONEY_TOKEN, 'overall_player_board_'+player_id ); </pre> Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''addToStockWithId( type, id, from )''' This is exactly the same method than "addToStock", except that you associate an ID to the newly created item. This is especially useful: * When you need to know which item(s) has been selected by the user (see "getSelectedItems"). * When you need to remove a specific item from the stock with "removeFromStockById" Important: for a given stock control, you must use either addToStock or addToStockWithId, but NEVER BOTH OF THEM. '''removeFromStock( type, to )''' Remove an item of the specific type from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeFromStockById( id, to )''' Remove an item with a specific ID from the stock. "to" is an optional parameter. If "to" contains the ID of an HTML element, the item removed from the stock is slided to this HTML element before it disappear. '''removeAll()''' Remove all items from the stock. '''getPresentTypeList()''' Return an array with all the types of items present in the stock right now. Example: <pre> this.myStockControl.removeAll(); this.myStockControl.addToStock( 65 ); this.myStockControl.addToStock( 34 ); this.myStockControl.addToStock( 89 ); this.myStockControl.addToStock( 65 ); // The following returns: { 34:1, 65:1, 89:1 } var item_types = this.myStockControl.getPresentTypeList(); </pre> '''resetItemsPosition()''' If you moved an item from the stock control manually (ex: after a drag'n'drop) and want to reset their position to their original ones, you can call this method. '''item_margin''' By default, there is a margin of 5px between the items of a stock. You can change the member variable "item_margin" to change this. Example: <pre> this.myStockControl.item_margin=5; </pre> '''changeItemsWeight( newWeights )''' With this method you can change dynamically the weight of the item types in a stock control. Items are immediately re-sorted with the new weight. Example: with a stock control that contains classic cards, you can order them by value or by color. Using changeItemsWeight you can switch from one sort method to another when a player request this. newWeights is an associative array: item type id => new weight. Example: <pre> // Item type 1 gets a new weight of 10, 2 a new weight of 20, 3 a new weight of 30. this.myStockControl.changeItemsWeight( { 1: 10, 2: 20, 3: 30 } ); </pre> '''setSelectionMode( mode )''' For each stock control, you can specify a selection mode: * 0: no item can be selected by the player. * 1: a maximum of one item can be selected by the player at the same time. * 2 (default): several items can be selected by the player at the same time. '''setSelectionAppearance( type )''' For each stock control, you can specify a selection highlighting type: * 'border': there will be a red border around selected items (this is the default). The attribute 'apparenceBorderWidth' can be used to manage the width of the border (in pixels). * 'disappear': the selected item will fade out and disappear. This is useful when the selection has the effect of destroying the item. * 'class': there will be an extra 'stockitem_selecte' css class added to the element when it is selected (and removed when unselected). You can override this class in the css file for your game. By default this class definition is: <pre> .stockitem_selected { border: 2px solid red ! important; } </pre> If you want to override it for example to change the border color add this in your <game>.css file: <pre> .stockitem_selected { border: 2px solid orange ! important; } </pre> NB: the 'class' highlighting type has not yet been deployed on the studio - 24/02/2014. This warning will be removed after the next upgrade. '''isSelected( id )''' Return true/false wether the specified item id has been selected or not. '''selectItem( id )''' Select the specified item. '''unselectItem( id )''' Unselect the specified item. '''unselectAll()''' Unselect all items of the stock. '''onChangeSelection''' This callback method is called when the player select/unselect an item of the stock. You can connect this to one of your method like this: <pre> dojo.connect( this.myStockControl, 'onChangeSelection', this, 'onMyMethodToCall' ); (...) onMyMethodToCall: function( control_name ) { // This method is called when myStockControl selected items changed var items = this.myStockControl.getSelectedItems(); // (do something) }, </pre> Note: The "control_name" argument is the ID (the "DOM" id) of the "div" container of your stock control. Using "control_name", you can use the same callback method for different Stock control and see which one trigger the method. '''getSelectedItems()''' Return the list of selected items, as an array with the following format: <pre> [ { type:1, id: 1001 }, { type:1, id: 1002 }, { type:3, id: 1003 } ... ] </pre> '''getUnselectedItems()''' Same as the previous one, but return unselected item instead of seleted ones. '''getAllItems()''' Get all items (same format than getSelectedItems and getUnselectedItems). '''setOverlap( horizontal_percent, vertical_percent )''' Make items on the stock control "overlap" on each other, to save space. By default, horizontal_overlap and vertical_overlap are 0. When horizontal_overlap=20, it means that a stock item must overlap on 20% of the width of the previous item. horizontal_overlap can't be over 100. vertical_overlap works differently: one items on two are shifted up. See "Jaipur" game to see an example to use of this function. '''onItemCreate''' Using onItemCreate, you can trigger a method each time a new item is added to the Stock, in order you can customize it. Complete example: <pre> // During "setup" phase, we associate our method "setupNewCard" with the creation of a new stock item: this.myStockItem.onItemCreate = dojo.hitch( this, 'setupNewCard' ); (...) // And here is our "setupNewCard": setupNewCard: function( card_div, card_type_id, card_id ) { // Add a special tooltip on the card: this.addTooltip( card_div.id, _("Some nice tooltip for this item"), '' ); // Note that "card_type_id" contains the type of the item, so you can do special actions depending on the item type // Add some custom HTML content INSIDE the Stock item: dojo.place( this.format_block( 'jstpl_my_card_content', { .... } ), card_div.id ); } </pre> == Tips when adding/removing items to/from Stock components == The usual way is the following: '''Situation A''': When you add a card to a stock item, and this card is '''not''' coming from another stock: use "addToStockWithId" with a "from" argument set to the element of your interface where card should come from. '''Situation B''': When you add a card to a stock item, and this card is coming from another stock: * on the destination Stock, use "addToStockWithId" with a "from" equals to the HTML id of the corresponding item in the source Stock. For example, If the source stock id is "myHand", then the HTML id of card 48 is "myHand_item_48". * then, remove the source item with "removeFromStockById". (note that it's important to do things in this order, because source item must still exists when you use it as the origin of the slide). '''Situation C''': When you move a card from a stock item to something that is not a stock item: * insert the card as a classic HTML template (dojo.place / this.format_block). * place it on the Stock item with "this.placeOnObject", using Stock item HTML id (see above). * slide it to its new position with "this.slideToObject" * remove the card from the Stock item with "removeFromStockById". Using the methods above, your cards should slide to, from and between your Stock controls smoothly 4dfcb274e569dab35f3940a3fbb9130f649dcbf2 Gamehelpyatzy 0 122 1189 1115 2014-07-27T16:21:13Z Smilelee 5918 wikitext text/x-wiki The game Yahtzee consists of 13 rounds. In each round, you roll 5 dice and then score the roll in a different category of your choice. During a round, you can roll the dice up to three times before scoring -- the initial roll (in which you must roll all the dice), plus two optional re-rolls of any or all dice. There are 13 scoring categories, and each must be used for one of the 13 rounds. This often results in a zero score for some categories. The 13 scoring categories are as follows: 1-6: There is one category for each number on the die. In these categories, the score is the sum of the pips on the dice of that number. For example, a roll of 1-1-2-5-5 could be scored as 2 points in the "ones" category, 2 points in the "twos" category, 10 points in the "fives" category, or 0 points in the "threes," "fours," or "sixes." If a player scores a total of at least 63 points across these six boxes, a bonus of 35 points is added. 7. Three-Of-A-Kind: At least three dice showing the same face -- Points equal the sum of all 5 dice (not just the 3 of a kind) 8. Four-Of-A-Kind: At least four dice showing the same face -- Points equal the sum of all 5 dice (not just the 4 of a kind) 9. Full House: A three-of-a-kind and a pair -- 25 points 10. Small Straight: Four sequential dice 1-2-3-4, 2-3-4-5, or 3-4-5-6) -- 30 points 11. Large Straight: Five sequential dice (1-2-3-4-5 or 2-3-4-5-6) -- 40 points 12. Yahtzee: All five dice showing the same face -- 50 points (plus, once you have scored 50 pts for a Yahtzee, a 2nd Yahtzee gives a bonus of 100 points) 13. Chance: Any combination -- points equal the sum of all 5 dice 61659114df2b62dcc4d529620aa617f32d294b06 Zone 0 113 1192 772 2014-08-06T09:30:52Z Sourisdudesert 1 wikitext text/x-wiki The Zone component is meant to organise items of the same type inside a predefined space. == Zone in action == If you want to see how Zone works, please try "Can't Stop" or "Niagara" on BGA, or watch a game in progress or game replay. In Can't Stop, zone is used to display the bhikkus ascending the mountain when there is more than one on the same space (diagonal mode). In Niagara, it is used to display the canoes over the circles going down the river (custom mode). == How to use Zone == At first, don't forget to add "ebg/zone" as a dependency: <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/zone" /// <==== HERE ], </pre> Then, declare a new variable in your class for the Zone object: <pre> constructor: function(){ console.log('yourgame constructor'); // Zone control this.myZone = new ebg.zone(); </pre> Now, in your template file, you must add a div that will host this zone: <pre> <div id="my_zone"></div> </pre> And set its width (and optionnaly, height and position) in CSS: <pre> #my_zone { width: 100px; } </pre> Then in your Javascript setup, attach your Zone component to the div and define its properties : <pre> zone.create( this, 'my_zone', <item_width>, <item_height> ); zone.setPattern( <mode> ); </pre> * <item_width> is an integer for the width of the objects you want to organise in the zone * <item_height> is an integer for the height of the objects you want to organise in the zone * <mode> is one of 'grid' (objects will be put on lines from top left to bottom right, wrapping when there is not enough space left on the line) 'diagonal' (objects will be organised on a top left to bottom right diagonal, overlapping each other) or 'custom' (objects will be organised depending upon their number and the coordinates that you provide - see below) Now your zone is ready to be used! After creating an object that you want to add to the zone as a classic HTML template (dojo.place / this.format_block), you can simply use: <pre> zone.placeInZone( <object_id>, <weight> ); </pre> * <object_id> is the string identifier for your object 'my_object_id' * <weight> is an optional parameter used to sort items To remove an item, use: <pre> zone.removeFromZone( <object_id>, <destroy?>, <to> ); </pre> * <object_id> is the string identifier for your object 'my_object_id' * <destroy?> is a boolean indicating if the object should be destroyed after being removed * <to> is the destination the object must be slided to when being removed (before being eventually destroyed) You can also: * remove all items from the zone (and destroy them) using zone.removeAll(); * get the number of items in your zone using zone.getItemNumber(); * get an array of the ids of all the items using zone.getAllItems(); == Custom mode == If you want complete control on how your objects are laid out inside the Zone, you can determine their coordinates after their number when being added to the zone. Here is how to do it, when defining your Zone properties in the javascript setup: <pre> this.zone.setPattern( 'custom' ); this.zone.itemIdToCoords = function( i, control_width ) { if( i%8==0 ) { return { x:1,y:19, w:60, h:30 }; } else if( i%8==1 ) { return { x:30,y:38, w:60, h:30 }; } else if( i%8==2 ) { return { x:42,y:8, w:60, h:30 }; } else if( i%8==3 ) { return { x:5,y:58, w:60, h:30 }; } else if( i%8==4 ) { return { x:5,y:24, w:60, h:30 }; } else if( i%8==5 ) { return { x:35,y:43, w:60, h:30 }; } else if( i%8==6 ) { return { x:47,y:13, w:60, h:30 }; } else if( i%8==7 ) { return { x:10,y:63, w:60, h:30 }; } }; </pre> c1b2572f7689f9a3d9b9c3d1e526caa08a9f162d Gamehelpsaboteur 0 32 1195 1025 2014-08-14T05:59:55Z Chaotic iak 3338 wikitext text/x-wiki == Goal == Get as many gold nuggets as possible during the three rounds of the game. In order to do so, # if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards # if you are a '''saboteur''', you must, in association with other saboteurs, prevent the gold diggers from getting to the treasure. Your role (gold digger or saboteur) will be randomly selected at the start of each round. == Rules summary == On your turn, you must click on a card from your hand to select it, then play this card or discard it. You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card. The cards are of several types: * 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card. * 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score). * 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you. * 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about. * 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove. == Cards in play == * 44 'Path' cards * 9 'Sabotage' cards (three for each tool) * 6 'Repair a tool' cards (two for each tool) * 3 'Repair a tool among these two' cards (one for each combination of two tools) * 5 'Map' cards (one less than in the box set, as requested by the game author) * 3 'Rock fall' cards * 28 'Gold' cards ** 16 with one gold nugget ** 8 with two gold nuggets ** 4 with three gold nuggets == Roles == Roles are randomly selected among a set that depends upon the number of players: * with 3 players: 1 saboteur and 3 gold diggers * with 4 players: 1 saboteur and 4 gold diggers * with 5 players: 2 saboteurs and 4 gold diggers * with 6 players: 2 saboteurs and 5 gold diggers * with 7 players: 3 saboteurs and 5 gold diggers * with 8 players: 3 saboteurs and 6 gold diggers * with 9 players: 3 saboteurs and 7 gold diggers * with 10 players: 4 saboteurs and 7 gold diggers == Available variants == The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum! Two variants are about gold sharing: * '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed! * '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!) Two variants are about gameplay: * '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose! * '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded) == Saboteur 2 == Saboteur 2 introduces additional roles and actions. Now there are six roles: * '''Blue diggers (4)''' and '''green diggers (4)''' are the equivalent of the original gold diggers, but are now separated into two teams. They both want to reach the gold, but only the one that connects to the treasure wins. The team that wins is also affected by doors; see below. * '''Saboteurs (3)''' want to sabotage the connection, just like in the original game. * '''Boss (1)''' wins if either digger team wins. '''Profiteer (1)''' wins in all cases, whether it's either digger team or it's the saboteurs! * '''Geologists (2)''' don't care about gold; they care about gems that appear on tunnels as the dwarfs dig through. There are various new items and actions. * The '''path cards''' are complemented with additional cards. In particular, there is a bridge card, that allows a straight connection between opposite ends, but don't merge together like a crossroad does. * Some path cards have '''gems'''. These are only for the geologists; they don't block the path. * Some path cards have '''doors'''. These block the path of the opposing color. Only blue diggers can pass through blue doors, and only green diggers can pass through green doors. * Some path cards have '''ladders'''. These are connected to the starting ladder. This means you can start a path from any ladder onwards, even if it's not connected to the start. This also means doors behind ladders have no effect. * Action cards '''Theft (4)''' allow a player to prepare a theft. At the end of the round, each player with a theft may choose someone to steal a gold from. Action card '''Hands Off (3)''' stop a player from doing a theft. * Action cards '''Trapped! (3)''' put another player to jail, similar to a broken tool with one exception in the scoring. Action cards '''Free at Last! (4)''' free a player from jail. * Action cards '''Swap Your Hats (2)''' change the role of a player to another. These can be played to oneself or to someone else. * Action cards '''Swap Your Hands (2)''' allow a player to swap hands with another player. The other player gets to draw a replacement card. * Action cards '''Inspection (2)''' allow a player to look at the role of another player. There are new rules. * Each player has 6 cards on their hand at the beginning. * A player may discard 1-3 cards and draw the same number of replacement cards, instead of the original only 1. * A player may also discard 2 cards to remove any card (broken tool or jailed) in front of them, but they only get 1 replacement card. This reduces their hand size. And there is a completely hauled scoring method. * If there is a path to the gold card blocked by some door, the winner is the team that is not blocked by a door of opposing color. For example, if the path to the gold is blocked by a blue door, only the blue diggers win, no matter who placed the last card. ''If the path is blocked by both doors, then only the boss and the profiteer wins!'' * If there is a path to the gold card, not blocked by any door, then the winner is the team that makes the last connection, or both teams in case that connection is made by a non-digger. For example, if a green digger completes a path without doors, the green team wins. If a geologist completes the path instead, both teams win. * If there is no path to the gold card when everyone runs out of cards, the saboteurs win. * The number of winners, except geologists, is counted. This number is subtracted from 6, giving the number of gold pieces that each winner gets. For example, if the blue team with 2 people win together with a boss, then there are 3 winners, so each player gets 3 gold pieces. If there are 5 or more winners, each winner gets 1 gold piece. * However, boss receives 1 less gold pieces and profiteer receives 2 less gold pieces (cannot go below zero). In the example above, the boss receives 2 gold pieces instead of 3. * Geologists receive as many gold pieces as there are crystals at the end of the round. In case both geologists are present, this number is divided by two, rounded down. So if there are 5 crystals, a single geologist gets 5 gold pieces, while two geologists in play receive 2 gold pieces each. * The number of gold pieces a player has is not revealed to others (use your memory!), unless a variant '''Visible golds''' is used. == Anthem == The Official Anthem of Saboteur designed by ''Dzikidon'' and ''Sikora8a'' Music - '''Adele - Skyfall''': <nowiki> This is the end Hold your breath and count to ten Feel the Earth move and then Hear your axe burst again For this is the end I've digged and dreamt this moment I will repair I owe them Even tho' I'm broken Let the rock fall When it crumbles We will stand tall Face it all together Let the rock fall When it crumbles We will stand tall Face it all together At rock fall At rock fall Rock fall is where we start A thousand miles and cards apart Where roads collide and caves are dark You may fix my trolley You can break my lamp But you'll never have my gold Let the rock fall (Let the rock fall) When it crumbles (When it crumbles) We will stand tall (We will stand tall) Face it all together Let the rock fall (Let the rock fall) When it crumbles (When it crumbles) We will stand tall (We will stand tall) Face it all together At rock fall (Let the rock fall) When it crumbles We will stand tall) / x2 Where you go I go What you see I see I know I'd never be me Without the security Of your fixing cards Keeping me from harm Put your end in their straight And we'll stand Let the rock fall (Let the rock fall) When it crumbles (When it crumbles) We will stand tall (We will stand tall) Face it all together Let the rock fall (Let the rock fall) When it crumbles (When it crumbles) We will stand tall (We will stand tall) Face it all together At rock fall Let the rock fall We will stand tall At rock faaall </nowiki> f1a5b36c214282c88d973f7e9b810b8e9c9c269d 1196 1195 2014-08-14T06:01:18Z Chaotic iak 3338 /* Anthem */ wikitext text/x-wiki == Goal == Get as many gold nuggets as possible during the three rounds of the game. In order to do so, # if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards # if you are a '''saboteur''', you must, in association with other saboteurs, prevent the gold diggers from getting to the treasure. Your role (gold digger or saboteur) will be randomly selected at the start of each round. == Rules summary == On your turn, you must click on a card from your hand to select it, then play this card or discard it. You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card. The cards are of several types: * 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card. * 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score). * 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you. * 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about. * 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove. == Cards in play == * 44 'Path' cards * 9 'Sabotage' cards (three for each tool) * 6 'Repair a tool' cards (two for each tool) * 3 'Repair a tool among these two' cards (one for each combination of two tools) * 5 'Map' cards (one less than in the box set, as requested by the game author) * 3 'Rock fall' cards * 28 'Gold' cards ** 16 with one gold nugget ** 8 with two gold nuggets ** 4 with three gold nuggets == Roles == Roles are randomly selected among a set that depends upon the number of players: * with 3 players: 1 saboteur and 3 gold diggers * with 4 players: 1 saboteur and 4 gold diggers * with 5 players: 2 saboteurs and 4 gold diggers * with 6 players: 2 saboteurs and 5 gold diggers * with 7 players: 3 saboteurs and 5 gold diggers * with 8 players: 3 saboteurs and 6 gold diggers * with 9 players: 3 saboteurs and 7 gold diggers * with 10 players: 4 saboteurs and 7 gold diggers == Available variants == The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum! Two variants are about gold sharing: * '''Old Mine''': the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed! * '''New mine''': the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!) Two variants are about gameplay: * '''Competitive''': the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose! * '''Selfish dwarf''': one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded) == Saboteur 2 == Saboteur 2 introduces additional roles and actions. Now there are six roles: * '''Blue diggers (4)''' and '''green diggers (4)''' are the equivalent of the original gold diggers, but are now separated into two teams. They both want to reach the gold, but only the one that connects to the treasure wins. The team that wins is also affected by doors; see below. * '''Saboteurs (3)''' want to sabotage the connection, just like in the original game. * '''Boss (1)''' wins if either digger team wins. '''Profiteer (1)''' wins in all cases, whether it's either digger team or it's the saboteurs! * '''Geologists (2)''' don't care about gold; they care about gems that appear on tunnels as the dwarfs dig through. There are various new items and actions. * The '''path cards''' are complemented with additional cards. In particular, there is a bridge card, that allows a straight connection between opposite ends, but don't merge together like a crossroad does. * Some path cards have '''gems'''. These are only for the geologists; they don't block the path. * Some path cards have '''doors'''. These block the path of the opposing color. Only blue diggers can pass through blue doors, and only green diggers can pass through green doors. * Some path cards have '''ladders'''. These are connected to the starting ladder. This means you can start a path from any ladder onwards, even if it's not connected to the start. This also means doors behind ladders have no effect. * Action cards '''Theft (4)''' allow a player to prepare a theft. At the end of the round, each player with a theft may choose someone to steal a gold from. Action card '''Hands Off (3)''' stop a player from doing a theft. * Action cards '''Trapped! (3)''' put another player to jail, similar to a broken tool with one exception in the scoring. Action cards '''Free at Last! (4)''' free a player from jail. * Action cards '''Swap Your Hats (2)''' change the role of a player to another. These can be played to oneself or to someone else. * Action cards '''Swap Your Hands (2)''' allow a player to swap hands with another player. The other player gets to draw a replacement card. * Action cards '''Inspection (2)''' allow a player to look at the role of another player. There are new rules. * Each player has 6 cards on their hand at the beginning. * A player may discard 1-3 cards and draw the same number of replacement cards, instead of the original only 1. * A player may also discard 2 cards to remove any card (broken tool or jailed) in front of them, but they only get 1 replacement card. This reduces their hand size. And there is a completely hauled scoring method. * If there is a path to the gold card blocked by some door, the winner is the team that is not blocked by a door of opposing color. For example, if the path to the gold is blocked by a blue door, only the blue diggers win, no matter who placed the last card. ''If the path is blocked by both doors, then only the boss and the profiteer wins!'' * If there is a path to the gold card, not blocked by any door, then the winner is the team that makes the last connection, or both teams in case that connection is made by a non-digger. For example, if a green digger completes a path without doors, the green team wins. If a geologist completes the path instead, both teams win. * If there is no path to the gold card when everyone runs out of cards, the saboteurs win. * The number of winners, except geologists, is counted. This number is subtracted from 6, giving the number of gold pieces that each winner gets. For example, if the blue team with 2 people win together with a boss, then there are 3 winners, so each player gets 3 gold pieces. If there are 5 or more winners, each winner gets 1 gold piece. * However, boss receives 1 less gold pieces and profiteer receives 2 less gold pieces (cannot go below zero). In the example above, the boss receives 2 gold pieces instead of 3. * Geologists receive as many gold pieces as there are crystals at the end of the round. In case both geologists are present, this number is divided by two, rounded down. So if there are 5 crystals, a single geologist gets 5 gold pieces, while two geologists in play receive 2 gold pieces each. * The number of gold pieces a player has is not revealed to others (use your memory!), unless a variant '''Visible golds''' is used. == Anthem == The Official Anthem of Saboteur designed by ''Dzikidon'' and ''Sikora8a'' Music - '''Adele - Skyfall''': *This is the end *Hold your breath and count to ten *Feel the Earth move and then *Hear your axe burst again *For this is the end *I've digged and dreamt this moment *I will repair I owe them *Even tho' I'm broken *Let the rock fall *When it crumbles *We will stand tall *Face it all together *Let the rock fall *When it crumbles *We will stand tall *Face it all together *At rock fall *At rock fall *Rock fall is where we start *A thousand miles and cards apart *Where roads collide and caves are dark *You may fix my trolley *You can break my lamp *But you'll never have my gold *Let the rock fall (Let the rock fall) *When it crumbles (When it crumbles) *We will stand tall (We will stand tall) *Face it all together *Let the rock fall (Let the rock fall) *When it crumbles (When it crumbles) *We will stand tall (We will stand tall) *Face it all together *At rock fall *(Let the rock fall) *When it crumbles *We will stand tall) / x2 *Where you go I go *What you see I see *I know I'd never be me *Without the security *Of your fixing cards *Keeping me from harm *Put your end in their straight *And we'll stand *Let the rock fall (Let the rock fall) *When it crumbles (When it crumbles) *We will stand tall (We will stand tall) *Face it all together *Let the rock fall (Let the rock fall) *When it crumbles (When it crumbles) *We will stand tall (We will stand tall) *Face it all together *At rock fall *Let the rock fall *We will stand tall *At rock faaall 60486c51f4817bd9d60805b9914c8a7ce9b21102 The Boss 0 46 1197 906 2014-08-14T08:35:29Z Chaotic iak 3338 wikitext text/x-wiki The Boss is a game of logical deduction and bluffing, set as a large gangster group on the cities of USA. == Objective == Be the player with the most money at the end of the game. == Mechanics == Several '''character cards''' are dealt at the beginning of the game and will not change during the game. The characters used depend on the number of players. The character card shows several symbols, indicating the list of '''city cards''' associated with it. For example, the character (on) Detroit (colored blue) has five city cards: four showing various number of money bags (1, 2, 3, 4), and one gun. The only exception is '''Chicago''' (red), which has no city cards associated with it. At the beginning of a hand, one associated city card is dealt face down under each character card (except Chicago), and the remaining city cards are distributed evenly to the players (5 for 2-4 players and 4 for 5-6 players). At the end of the hand, the city card below each character card is the reward for each character, claimed by the player with the majority on the character card. Hence, the city cards held by each player gives them information on what city card can be the reward, by ruling out some possibilities. Each player has 9 gangsters, divided into 6 Experts (permanent gangsters, can be reused), and 3 Occasionals (temporary gangsters, can only be used once). These are the gangsters that fight for majority for each character. == One hand == === Beginning of hand === At the beginning of a hand, each character card has one face down city card, as described above. At the beginning of the game, the Chicago card is located on the second position, while the remaining cards are ordered according to their numbers. Later, after each hand, the Chicago card moves right; see below. One player holds the '''starting player marker''', which begins the hand. After a player plays, the turn passes over clockwise. The player currently playing will perform two phases: === Phase 1: Placing gangsters === The player ''may'' play some of their gangsters to a ''single'' character card, deploying their gangsters there. There are a few rules: * After playing their gangsters, the player must have the most gangsters on the character card. Experts and occasionals are counted equally. For example, if player Red has 2 gangsters on New York and player Green has 4 gangsters on it, Red must play at least 3 more gangsters on New York to gain majority (5 vs 4) or decide to play somewhere else. * An occasional must be accompanied by an expert on the character card, either played earlier or played together, although a single expert suffices to accompany all three occasionals. * A player may not play on Chicago before playing somewhere else. === Phase 2: Revealing a city card === The player ''must'' play a city card, putting it next to the corresponding character card, thus revealing information about that city (of which option cannot be the face down card). === Last two turns of the hand === When the starting player (the one with the marker) wants to play and they have only two cards on their hand, they reveal one police card. Police cards determine the end of the game, and are explained in more details below. === Last turn of the hand === When the fourth turn of each player ends (all players have one card left), the order of play is changed. Now the player with the most gangsters (experts and occasionals) plays first, in decreasing order of number of gangsters, until the player with the least gangsters plays last. In case of a tie, the same order (starting from the player with the marker and going clockwise) is used for those players. === End of hand === After all cards are played, the hand ends. Each face down city card is revealed, and the player with the most gangsters played on the city gains the "reward". There are several kinds of city cards: * '''Money bag with a number''': A money bag is worth one million dollars, the unit of the game. Win the shown amount of money. * '''Theft''': Lose two million dollars. * '''4 Shoot-Out''': Win four million dollars. Additionally, for each player having a gangster on the city that is not the winner, kill one of their experts. * '''Banished''': The "winner" may no longer play gangsters here for the rest of the game. * '''Hospital''': The "winner" loses one expert due to injury, which must be put to the hospital for the next hand. After that, the expert is retrieved back. * '''Prison''': The "winner" loses one expert due to being caught, which must be put to the prison for the next two hands. After that, the expert is retrieved back. * '''Revolver''': The "winner" loses one expert, killed by a gun. The expert is removed from the rest of the game. Chicago is scored differently. The winner on Chicago first computes the number of money bags ''last played'' for the cities to the left of it, and gains that many money bags, divided by two, rounded down. For example, suppose the Chicago is after Boston (yellow), with New York (black) and Boston to the left of it. Also suppose that after the hand, the 3 million card is played last on New York and the prison card is played last on Boston. Then the winner on Chicago wins the number of money bags to the left, 3 (New York) plus 0 (Boston), divided by two, which means 3/2 = 1 million. === Preparation for next hand === After each hand, if it's not the end of game yet, move the starting player marker clockwise and move the Chicago card one step to the right (swapping with the card to its right). == End of game == Each hand, after the third turn of each player, a police card is revealed. There are five police cards. Two have silver badges, two have gold badges, and one has both badges. When three badges of the same color are revealed, it signals the end of the game; after the current hand finishes, the game ends. The winner is the player with the most money bags. ee12781fe772d93dc9b4d7930e5c68dcbf385233 Your game state machine: states.inc.php 0 90 1198 1149 2014-08-22T04:23:22Z Pikiou 1872 /* args */ warning about the "args" method being called before the "action" method wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. Note: When a game is in prod and you change the ID of a state, all active games (including many turn based) will behave unpredictably. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "args" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> === args === (optional) From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state. Example 1 : for Reversi, the list of possible moves during playerTurn state. Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor. Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them. In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them. Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array. Let's see a complete example using args with « Reversi » game : In states.inc.php, we specify some « args » argument for gamestate « playerTurn » : <pre> 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", <================================== HERE "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), </pre> It corresponds to a « argPlayerTurn » method in our PHP code (reversi.game.php): <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves() ); } </pre> Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn : <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> Note: you can also use values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above). Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn). Warning: the "args" method can be called before the "action" method so don't expect data modifications by the "action" method to be available in the "args" method! ==== Private infos in args ==== By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic. This is although possible to specify that some data should be sent to some specific players only: Example 1: send an information to active player(s) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private 'active' => array( // Using "active" keyword inside "_private", you select active player(s) 'somePrivateData' => self::getSomePrivateData() // will be send only to active player(s) ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> Inside the js file, these variables will be available through `args._private`. (e.g. `args._private.somePrivateData` -- it is not `args._private.active.somePrivateData` nor is it `args.somePrivateData`) Example 2: send an information to a specific player (<specific_player_id>) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private <specific_player_id> => array( // you select one specific player with its id 'somePrivateData' => self::getSomePrivateData() // will be send only to <specific_player_id> ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> IMPORTANT: in certain situation (ex: multipleactiveplayer game state) these "private data" features can have a big performance impact. Please do not use if not needed. === updateGameProgression === (optional) IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated. At least one of your game state (any of them) must specify updateGameProgression=>true. 9886f7c801e458aae7844af5814f3dbfb81e11f9 Main game logic: yourgamename.game.php 0 86 1199 1146 2014-08-22T04:25:53Z Pikiou 1872 /* Notify players */ Warning about ignored notifications at game start wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> ; function getNonEmptyObjectFromDB( $sql ) : Idem, but raise an exception if the query doesn't return exactly one row Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. Notifications sent between the game start (setupNewGame) and the end of the "action" method of the first active state will never reach their destination. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array. Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. e4d8222ebffd957221d3ed981fc0484ba2e6eda1 Gamehelpthroughtheages 0 168 1200 1191 2014-08-23T05:28:34Z Rainn 5818 wikitext text/x-wiki During your turn, you may spend your '''actions points''' to: * pick cards from the card rows (if you have room in your hand) * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * build/upgrade military units '''Yellow counters''' represent your population. They can be in one of three places: * on the cards on your tableau * on your available worker pool * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in two places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce food or resources Building up your civilisation: * '''Food''' lets you move workers from your yellow bank to your available worker pool. * '''Resources''' let you move workers from your available worker pool to a card on your tableau. * '''Science''' (light bulbs) lets you move cards from your hand to your tableau. * When your population grows, you will need to produce more '''happiness''' or your workers will stop working. * Producing '''culture''' will earn you victory points. * Producing more '''military strength''' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars In the Advanced and Complete games, '''additional points are scored at the end of the game''' according to special event cards. But at the end of the Simple game, additional points are scored the same way every game: * 2 culture scored per 1 Strength (military) * 2 culture scored per Happy Face * 2 culture scored per level 1 technology in play * 1 culture scored per food or resource production per turn * 1 culture scored per 1 Science Rating (science gained per turn) f496255c51b2ad6b2484d256be3bc44e649e5df7 Gamehelpseasons 0 43 1201 900 2014-08-25T05:45:43Z Dralkyr 6346 Updated the bonus penalty to reflect current rules wikitext text/x-wiki Seasons is a game of generating points (crystals) by choosing the correct combination of dice and the activation of card powers. The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be returned to the player on the starting of each cycle. Each player can choose only one die per turn. The effects are as follows: ''Star'' - increase the maximum card player can summon (max 15) ''Elements'' - Gain an energy of the element shown (water, earth, air, fire) ''Numbers'' - Gain the number of Crystals as indicated by the number ''Square card'' - Draw a card ''Dice with frames surrounding'' - Allow user to transmute energy into crystal (depend on which part of the game is at) ''Dots'' - Indicate how fast the marker progresses through the seasons cycle There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 12 for the 2nd and 20 for the 3rd. There are 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element, and allow user to choose a card out of 2 cards (must use with draw card dice). At the end of the game the points are calculated by adding the numbers on each played card and the crystal owned and substracting 5 points for each power card remaining in hand. The player with the most victory points wins. Note: Users need to discard energy immediately if the energy is more than the slots allocated. If a card allows you to summon another card but you have no space for this second card then it (the second card) will be discarded with no refund. == Difficulty levels: == '''Apprentice wizard level''' In order to make the game easier to learn, there are “pre-constructed” sets of nine power cards. Instead of taking step 1 of the first game phase, each player gets one of these sets. '''Magician level''' Only the power cards numbered 1 to 30 are in play. These cards have easy to grasp effects and will allow you to slowly discover the world of Seasons. '''Archmage level''' All 50 kinds of power cards are in play. The cards numbered 31 through 50 have more complex effects than the basic cards, but will allow you to extend the fun of playing by discovering new effects and combinations. 8e6f04ed3f186dea3ad3e37741a7eb05ebfc4fa9 TermsOfService 0 170 1204 1203 2014-08-29T09:10:28Z Sourisdudesert 1 /* About Software in our Services */ wikitext text/x-wiki = Board Game Arena Terms of Service = == Welcome to BGA! == Thanks for using our services (“Services”). The Services are provided by Board Game Arena ("BGA"), located at G. Isabelli, 19 bd de la République, 92260 Fontenay-aux-Roses, France. By using our Services, you are agreeing to these terms. Please read them carefully. == Using our Services == You must follow any policies made available to you within the Services. Don’t misuse our Services. For example, don’t interfere with our Services or try to access them using a method other than the interface and the instructions that we provide. You may use our Services only as permitted by law, including applicable export and re-export control laws and regulations. We may suspend or stop providing our Services to you if you do not comply with our terms or policies or if we are investigating suspected misconduct. Using our Services does not give you ownership of any intellectual property rights in our Services or the content you access. You may not use content from our Services unless you obtain permission from its owner or are otherwise permitted by law. These terms do not grant you the right to use any branding or logos used in our Services. Don’t remove, obscure, or alter any legal notices displayed in or along with our Services. Our Services display some content that is not from BGA. This content is the sole responsibility of the entity that makes it available. We may review content to determine whether it is illegal or violates our policies, and we may remove or refuse to display content that we reasonably believe violates our policies or the law. But that does not necessarily mean that we review content, so please don’t assume that we do. In connection with your use of the Services, we may send you service announcements, administrative messages, and other information. You may opt out of some of those communications. == Your BGA Account == You may need a BGA Account in order to use some of our Services. You may create your own BGA Account, or your BGA Account may be assigned to you by an administrator, such as your employer or educational institution. If you are using a BGA Account assigned to you by an administrator, different or additional terms may apply and your administrator may be able to access or disable your account. To protect your BGA Account, keep your password confidential. You are responsible for the activity that happens on or through your BGA Account. Try not to reuse your BGA Account password on third-party applications. If you learn of any unauthorized use of your password or BGA Account, please change it immediately from your preferences. == Your responsibility as a BGA player ("the Player") == 1) The Player is solely responsible for any messages, content and information posted by him on the site since, in its capacity as host of the service considered here, under the provisions of Law No. 2004 -575 of 21 June 2004 on confidence in the digital economy, BGA can not be responsible for the content posted or transmitted by Players on the Site and on which BGA exercises no control and monitoring. The Player expressly agrees, under penalty of criminal responsibility or civil liability, that it broadcasts messages are not likely to, without this list is exhaustive, including: - violate intellectual property rights of third parties: in this respect the Player undertakes not to reproduce or communicate publicly on the Site or the material protected under copyright, trademark filed as or more generally protected by other intellectual property rights held by third parties without the prior consent of the holders of such proprietary rights. - Contain computer viruses likely to interrupt, destroy or impair the functionality of the Site; - Being an apologist for crimes or contain illegal messages, threatening, or pedophile nature, pornographic, defamatory, obscene, hateful, racist, antisemitic, xenophobic, revisionist or contrary to public order or morality; - Infringe privacy or dignity of others; - Incite violence, fanaticism, crime, suicide, hatred due to religion, race, gender, sexual orientation, ethnicity, - Harass other players with whom the Player would be contacted when discussing the different communication areas of the site; - Promote or encourage any criminal activity or enterprise; - Solicit and / or disclose passwords and / or personal information for commercial or unlawful purposes; - Transmit any chain e-mails, unsolicited mass mailings, instant messages, commercials or unwanted unsolicited mail; - Contain advertisements and / or solicitations to offer products and / or commercial services through the Site. - Contain addresses or hypertext links to external sites whose content is contrary to the laws and regulations, which violate the rights of others or is contrary to these terms. 2) The Player agrees to hold only one account on BGA, unless otherwise approved by BGA. We reserve the right to terminate any multiple accounts attributable to the same person. 3) The Player agrees not to resort to the use of automated systems such as scripts to play or send messages. 4) The Player is solely responsible for keeping and confidentiality of their password and agrees not to communicate at any time whatsoever, his password to any other player or to use the account, the username and password of another Player. It also undertakes not to create multiple accounts. The Player guarantees the accuracy of information provided to BGA for purposes of registration and agrees to notify any subsequent changes. 5) The Player acknowledges that BGA reserves, in case his use of the site would be contrary to these Terms and generally applicable laws and regulatory provisions in force, to immediately and without notice of its deregistration Site services and / or blocking its access to the Site. 6) BGA reserves, assuming the Player would be responsible for an offense under the legislation or affect the rights of third parties the right to provide, upon request of all legitimate authority (courts, administrative authorities, police), all information allowing or facilitating the identification of the offending Player. 7) The Player is required to notify BGA, using the "Report this player" function, any misuse of the Site which he has knowledge, including any message whose contents violate the above prohibitions set or more generally applicable laws and regulatory provisions in force. == Privacy and Copyright Protection == BGA's [http://boardgamearena.com/#!doc/privacy privacy policies] explain how we treat your personal data and protect your privacy when you use our Services. By using our Services, you agree that BGA can use such data in accordance with our privacy policies. We respond to notices of alleged copyright infringement and terminate accounts of repeat infringers according to the process set out in France and the European Union. If you think somebody is violating your copyrights and want to notify us, you can contact us directly though our "Contact" section. BGA wishes to place a cookie on the computer of the subscriber. A cookie can not be personally identified. However, it records information relating to the navigation of the computer on the Site (pages viewed, date and time of visit, etc.). BGA that can read during subsequent visits. This will allow for easier navigation and avoid having to provide each new visit the information already sent an earlier date. It is stated that the shelf life of "cookies" BGA implanted is less than 6 (six) months. BGA notify the Player that the setting of their browser to alert you of the presence of "cookies" and that he may oppose the registration of "cookies". == Your Content in our Services == Some of our Services allow you to upload, submit, store, send or receive content. You retain ownership of any intellectual property rights that you hold in that content. In short, what belongs to you stays yours. When you upload, submit, store, send or receive content to or through our Services, you give BGA (and those we work with) a worldwide license to use, host, store, reproduce, modify, create derivative works (such as those resulting from translations, adaptations or other changes we make so that your content works better with our Services), communicate, publish, publicly perform, publicly display and distribute such content. The rights you grant in this license are for the limited purpose of operating, promoting, and improving our Services, and to develop new ones. This license continues even if you stop using our Services. Some Services may offer you ways to access and remove content that has been provided to that Service. Also, in some of our Services, there are terms or settings that narrow the scope of our use of the content submitted in those Services. Make sure you have the necessary rights to grant us this license for any content that you submit to our Services. Our automated systems analyze your content to provide you personally relevant features. This analysis occurs as the content is sent, received, and when it is stored. You can find more information about how BGA uses and stores content in the privacy policy or additional terms for particular Services. If you submit feedback or suggestions about our Services, we may use your feedback or suggestions without obligation to you. == About Software in our Services == When a Service requires or includes downloadable software, this software may update automatically on your device once a new version or feature is available. Some Services may let you adjust your automatic update settings. BGA gives you a personal, worldwide, royalty-free, non-assignable and non-exclusive license to use the software provided to you by BGA as part of the Services. This license is for the sole purpose of enabling you to use and enjoy the benefit of the Services as provided by BGA, in the manner permitted by these terms. You may not copy, modify, distribute, sell, or lease any part of our Services or included software, nor may you reverse engineer or attempt to extract the source code of that software, unless laws prohibit those restrictions or you have our written permission. Open source software is important to us. Some software used in our Services may be offered under an open source license that we will make available to you. There may be provisions in the open source license that expressly override some of these terms. == Modifying and Terminating our Services == We are constantly changing and improving our Services. We may add or remove functionalities or features, and we may suspend or stop a Service altogether. You can stop using our Services at any time, although we’ll be sorry to see you go. BGA may also stop providing Services to you, or add or create new limits to our Services at any time. We believe that you own your data and preserving your access to such data is important. If we discontinue a Service, where reasonably possible, we will give you reasonable advance notice and a chance to get information out of that Service. == Our Warranties and Disclaimers == We provide our Services using a commercially reasonable level of skill and care and we hope that you will enjoy using them. But there are certain things that we don’t promise about our Services. OTHER THAN AS EXPRESSLY SET OUT IN THESE TERMS OR ADDITIONAL TERMS, NEITHER BGA NOR ITS SUPPLIERS OR DISTRIBUTORS MAKE ANY SPECIFIC PROMISES ABOUT THE SERVICES. FOR EXAMPLE, WE DON’T MAKE ANY COMMITMENTS ABOUT THE CONTENT WITHIN THE SERVICES, THE SPECIFIC FUNCTIONS OF THE SERVICES, OR THEIR RELIABILITY, AVAILABILITY, OR ABILITY TO MEET YOUR NEEDS. WE PROVIDE THE SERVICES “AS IS”. SOME JURISDICTIONS PROVIDE FOR CERTAIN WARRANTIES, LIKE THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. TO THE EXTENT PERMITTED BY LAW, WE EXCLUDE ALL WARRANTIES. == Liability for our Services == WHEN PERMITTED BY LAW, BGA WILL NOT BE RESPONSIBLE FOR LOST PROFITS, REVENUES, OR DATA, FINANCIAL LOSSES OR INDIRECT, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES. TO THE EXTENT PERMITTED BY LAW, THE TOTAL LIABILITY OF BGA, AND ITS SUPPLIERS AND DISTRIBUTORS, FOR ANY CLAIMS UNDER THESE TERMS, INCLUDING FOR ANY IMPLIED WARRANTIES, IS LIMITED TO THE AMOUNT YOU PAID US TO USE THE SERVICES (OR, IF WE CHOOSE, TO SUPPLYING YOU THE SERVICES AGAIN). IN ALL CASES, BGA, AND ITS SUPPLIERS AND DISTRIBUTORS, WILL NOT BE LIABLE FOR ANY LOSS OR DAMAGE THAT IS NOT REASONABLY FORESEEABLE. == Business uses of our Services == If you are using our Services on behalf of a business, that business accepts these terms. It will hold harmless and indemnify BGA and its affiliates, officers, agents, and employees from any claim, suit or action arising from or related to the use of the Services or violation of these terms, including any liability or expense arising from claims, losses, damages, suits, judgments, litigation costs and attorneys’ fees. == About these Terms == We may modify these terms or any additional terms that apply to a Service to, for example, reflect changes to the law or changes to our Services. You should look at the terms regularly. Changes will be effective immediately. If you do not agree to the modified terms for a Service, you should discontinue your use of that Service. If there is a conflict between these terms and the additional terms, the additional terms will control for that conflict. These terms control the relationship between BGA and you. They do not create any third party beneficiary rights. If you do not comply with these terms, and we don’t take action right away, this doesn’t mean that we are giving up any rights that we may have (such as taking action in the future). If it turns out that a particular term is not enforceable, this will not affect any other terms. The laws of France will apply to any disputes arising out of or relating to these terms or the Services. All claims arising out of or relating to these terms or the Services will be litigated exclusively in the French courts. For information about how to contact BGA, please visit our [http://boardgamearena.com/#!doc/contact contact page]. be9d002e25f3d82aa26e8bb8c06904221abbeb27 1205 1204 2014-08-29T09:12:27Z Sourisdudesert 1 /* Your responsibility as a BGA player ("the Player") */ wikitext text/x-wiki = Board Game Arena Terms of Service = == Welcome to BGA! == Thanks for using our services (“Services”). The Services are provided by Board Game Arena ("BGA"), located at G. Isabelli, 19 bd de la République, 92260 Fontenay-aux-Roses, France. By using our Services, you are agreeing to these terms. Please read them carefully. == Using our Services == You must follow any policies made available to you within the Services. Don’t misuse our Services. For example, don’t interfere with our Services or try to access them using a method other than the interface and the instructions that we provide. You may use our Services only as permitted by law, including applicable export and re-export control laws and regulations. We may suspend or stop providing our Services to you if you do not comply with our terms or policies or if we are investigating suspected misconduct. Using our Services does not give you ownership of any intellectual property rights in our Services or the content you access. You may not use content from our Services unless you obtain permission from its owner or are otherwise permitted by law. These terms do not grant you the right to use any branding or logos used in our Services. Don’t remove, obscure, or alter any legal notices displayed in or along with our Services. Our Services display some content that is not from BGA. This content is the sole responsibility of the entity that makes it available. We may review content to determine whether it is illegal or violates our policies, and we may remove or refuse to display content that we reasonably believe violates our policies or the law. But that does not necessarily mean that we review content, so please don’t assume that we do. In connection with your use of the Services, we may send you service announcements, administrative messages, and other information. You may opt out of some of those communications. == Your BGA Account == You may need a BGA Account in order to use some of our Services. You may create your own BGA Account, or your BGA Account may be assigned to you by an administrator, such as your employer or educational institution. If you are using a BGA Account assigned to you by an administrator, different or additional terms may apply and your administrator may be able to access or disable your account. To protect your BGA Account, keep your password confidential. You are responsible for the activity that happens on or through your BGA Account. Try not to reuse your BGA Account password on third-party applications. If you learn of any unauthorized use of your password or BGA Account, please change it immediately from your preferences. == Your responsibility as a BGA player ("the Player") == 1) The Player is solely responsible for any messages, content and information posted by him on the site since, in its capacity as host of the service considered here, under the provisions of French Law No. 2004 -575 of 21 June 2004 on confidence in the digital economy, BGA can not be responsible for the content posted or transmitted by Players on the Site and on which BGA exercises no control and monitoring. The Player expressly agrees, under penalty of criminal responsibility or civil liability, that it broadcasts messages are not likely to, without this list is exhaustive, including: - violate intellectual property rights of third parties: in this respect the Player undertakes not to reproduce or communicate publicly on the Site or the material protected under copyright, trademark filed as or more generally protected by other intellectual property rights held by third parties without the prior consent of the holders of such proprietary rights. - Contain computer viruses likely to interrupt, destroy or impair the functionality of the Site; - Being an apologist for crimes or contain illegal messages, threatening, or pedophile nature, pornographic, defamatory, obscene, hateful, racist, antisemitic, xenophobic, revisionist or contrary to public order or morality; - Infringe privacy or dignity of others; - Incite violence, fanaticism, crime, suicide, hatred due to religion, race, gender, sexual orientation, ethnicity, - Harass other players with whom the Player would be contacted when discussing the different communication areas of the site; - Promote or encourage any criminal activity or enterprise; - Solicit and / or disclose passwords and / or personal information for commercial or unlawful purposes; - Transmit any chain e-mails, unsolicited mass mailings, instant messages, commercials or unwanted unsolicited mail; - Contain advertisements and / or solicitations to offer products and / or commercial services through the Site. - Contain addresses or hypertext links to external sites whose content is contrary to the laws and regulations, which violate the rights of others or is contrary to these terms. 2) The Player agrees to hold only one account on BGA, unless otherwise approved by BGA. We reserve the right to terminate any multiple accounts attributable to the same person. 3) The Player agrees not to resort to the use of automated systems such as scripts to play or send messages. 4) The Player is solely responsible for keeping and confidentiality of their password and agrees not to communicate at any time whatsoever, his password to any other player or to use the account, the username and password of another Player. It also undertakes not to create multiple accounts. The Player guarantees the accuracy of information provided to BGA for purposes of registration and agrees to notify any subsequent changes. 5) The Player acknowledges that BGA reserves, in case his use of the site would be contrary to these Terms and generally applicable laws and regulatory provisions in force, to immediately and without notice of its deregistration Site services and / or blocking its access to the Site. 6) BGA reserves, assuming the Player would be responsible for an offense under the legislation or affect the rights of third parties the right to provide, upon request of all legitimate authority (courts, administrative authorities, police), all information allowing or facilitating the identification of the offending Player. 7) The Player is required to notify BGA, using the "Report this player" function, any misuse of the Site which he has knowledge, including any message whose contents violate the above prohibitions set or more generally applicable laws and regulatory provisions in force. == Privacy and Copyright Protection == BGA's [http://boardgamearena.com/#!doc/privacy privacy policies] explain how we treat your personal data and protect your privacy when you use our Services. By using our Services, you agree that BGA can use such data in accordance with our privacy policies. We respond to notices of alleged copyright infringement and terminate accounts of repeat infringers according to the process set out in France and the European Union. If you think somebody is violating your copyrights and want to notify us, you can contact us directly though our "Contact" section. BGA wishes to place a cookie on the computer of the subscriber. A cookie can not be personally identified. However, it records information relating to the navigation of the computer on the Site (pages viewed, date and time of visit, etc.). BGA that can read during subsequent visits. This will allow for easier navigation and avoid having to provide each new visit the information already sent an earlier date. It is stated that the shelf life of "cookies" BGA implanted is less than 6 (six) months. BGA notify the Player that the setting of their browser to alert you of the presence of "cookies" and that he may oppose the registration of "cookies". == Your Content in our Services == Some of our Services allow you to upload, submit, store, send or receive content. You retain ownership of any intellectual property rights that you hold in that content. In short, what belongs to you stays yours. When you upload, submit, store, send or receive content to or through our Services, you give BGA (and those we work with) a worldwide license to use, host, store, reproduce, modify, create derivative works (such as those resulting from translations, adaptations or other changes we make so that your content works better with our Services), communicate, publish, publicly perform, publicly display and distribute such content. The rights you grant in this license are for the limited purpose of operating, promoting, and improving our Services, and to develop new ones. This license continues even if you stop using our Services. Some Services may offer you ways to access and remove content that has been provided to that Service. Also, in some of our Services, there are terms or settings that narrow the scope of our use of the content submitted in those Services. Make sure you have the necessary rights to grant us this license for any content that you submit to our Services. Our automated systems analyze your content to provide you personally relevant features. This analysis occurs as the content is sent, received, and when it is stored. You can find more information about how BGA uses and stores content in the privacy policy or additional terms for particular Services. If you submit feedback or suggestions about our Services, we may use your feedback or suggestions without obligation to you. == About Software in our Services == When a Service requires or includes downloadable software, this software may update automatically on your device once a new version or feature is available. Some Services may let you adjust your automatic update settings. BGA gives you a personal, worldwide, royalty-free, non-assignable and non-exclusive license to use the software provided to you by BGA as part of the Services. This license is for the sole purpose of enabling you to use and enjoy the benefit of the Services as provided by BGA, in the manner permitted by these terms. You may not copy, modify, distribute, sell, or lease any part of our Services or included software, nor may you reverse engineer or attempt to extract the source code of that software, unless laws prohibit those restrictions or you have our written permission. Open source software is important to us. Some software used in our Services may be offered under an open source license that we will make available to you. There may be provisions in the open source license that expressly override some of these terms. == Modifying and Terminating our Services == We are constantly changing and improving our Services. We may add or remove functionalities or features, and we may suspend or stop a Service altogether. You can stop using our Services at any time, although we’ll be sorry to see you go. BGA may also stop providing Services to you, or add or create new limits to our Services at any time. We believe that you own your data and preserving your access to such data is important. If we discontinue a Service, where reasonably possible, we will give you reasonable advance notice and a chance to get information out of that Service. == Our Warranties and Disclaimers == We provide our Services using a commercially reasonable level of skill and care and we hope that you will enjoy using them. But there are certain things that we don’t promise about our Services. OTHER THAN AS EXPRESSLY SET OUT IN THESE TERMS OR ADDITIONAL TERMS, NEITHER BGA NOR ITS SUPPLIERS OR DISTRIBUTORS MAKE ANY SPECIFIC PROMISES ABOUT THE SERVICES. FOR EXAMPLE, WE DON’T MAKE ANY COMMITMENTS ABOUT THE CONTENT WITHIN THE SERVICES, THE SPECIFIC FUNCTIONS OF THE SERVICES, OR THEIR RELIABILITY, AVAILABILITY, OR ABILITY TO MEET YOUR NEEDS. WE PROVIDE THE SERVICES “AS IS”. SOME JURISDICTIONS PROVIDE FOR CERTAIN WARRANTIES, LIKE THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. TO THE EXTENT PERMITTED BY LAW, WE EXCLUDE ALL WARRANTIES. == Liability for our Services == WHEN PERMITTED BY LAW, BGA WILL NOT BE RESPONSIBLE FOR LOST PROFITS, REVENUES, OR DATA, FINANCIAL LOSSES OR INDIRECT, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES. TO THE EXTENT PERMITTED BY LAW, THE TOTAL LIABILITY OF BGA, AND ITS SUPPLIERS AND DISTRIBUTORS, FOR ANY CLAIMS UNDER THESE TERMS, INCLUDING FOR ANY IMPLIED WARRANTIES, IS LIMITED TO THE AMOUNT YOU PAID US TO USE THE SERVICES (OR, IF WE CHOOSE, TO SUPPLYING YOU THE SERVICES AGAIN). IN ALL CASES, BGA, AND ITS SUPPLIERS AND DISTRIBUTORS, WILL NOT BE LIABLE FOR ANY LOSS OR DAMAGE THAT IS NOT REASONABLY FORESEEABLE. == Business uses of our Services == If you are using our Services on behalf of a business, that business accepts these terms. It will hold harmless and indemnify BGA and its affiliates, officers, agents, and employees from any claim, suit or action arising from or related to the use of the Services or violation of these terms, including any liability or expense arising from claims, losses, damages, suits, judgments, litigation costs and attorneys’ fees. == About these Terms == We may modify these terms or any additional terms that apply to a Service to, for example, reflect changes to the law or changes to our Services. You should look at the terms regularly. Changes will be effective immediately. If you do not agree to the modified terms for a Service, you should discontinue your use of that Service. If there is a conflict between these terms and the additional terms, the additional terms will control for that conflict. These terms control the relationship between BGA and you. They do not create any third party beneficiary rights. If you do not comply with these terms, and we don’t take action right away, this doesn’t mean that we are giving up any rights that we may have (such as taking action in the future). If it turns out that a particular term is not enforceable, this will not affect any other terms. The laws of France will apply to any disputes arising out of or relating to these terms or the Services. All claims arising out of or relating to these terms or the Services will be litigated exclusively in the French courts. For information about how to contact BGA, please visit our [http://boardgamearena.com/#!doc/contact contact page]. 05ca0eadf42866a1f921dbab43c40ce30ca8b91e 1206 1205 2014-08-29T09:13:55Z Sourisdudesert 1 /* Your responsibility as a BGA player ("the Player") */ wikitext text/x-wiki = Board Game Arena Terms of Service = == Welcome to BGA! == Thanks for using our services (“Services”). The Services are provided by Board Game Arena ("BGA"), located at G. Isabelli, 19 bd de la République, 92260 Fontenay-aux-Roses, France. By using our Services, you are agreeing to these terms. Please read them carefully. == Using our Services == You must follow any policies made available to you within the Services. Don’t misuse our Services. For example, don’t interfere with our Services or try to access them using a method other than the interface and the instructions that we provide. You may use our Services only as permitted by law, including applicable export and re-export control laws and regulations. We may suspend or stop providing our Services to you if you do not comply with our terms or policies or if we are investigating suspected misconduct. Using our Services does not give you ownership of any intellectual property rights in our Services or the content you access. You may not use content from our Services unless you obtain permission from its owner or are otherwise permitted by law. These terms do not grant you the right to use any branding or logos used in our Services. Don’t remove, obscure, or alter any legal notices displayed in or along with our Services. Our Services display some content that is not from BGA. This content is the sole responsibility of the entity that makes it available. We may review content to determine whether it is illegal or violates our policies, and we may remove or refuse to display content that we reasonably believe violates our policies or the law. But that does not necessarily mean that we review content, so please don’t assume that we do. In connection with your use of the Services, we may send you service announcements, administrative messages, and other information. You may opt out of some of those communications. == Your BGA Account == You may need a BGA Account in order to use some of our Services. You may create your own BGA Account, or your BGA Account may be assigned to you by an administrator, such as your employer or educational institution. If you are using a BGA Account assigned to you by an administrator, different or additional terms may apply and your administrator may be able to access or disable your account. To protect your BGA Account, keep your password confidential. You are responsible for the activity that happens on or through your BGA Account. Try not to reuse your BGA Account password on third-party applications. If you learn of any unauthorized use of your password or BGA Account, please change it immediately from your preferences. == Your responsibility as a BGA player ("the Player") == 1) The Player is solely responsible for any messages, content and information posted by him on the site since, in its capacity as host of the service considered here, under the provisions of French Law No. 2004 -575 of 21 June 2004 on confidence in the digital economy, BGA can not be responsible for the content posted or transmitted by Players on the Site and on which BGA exercises no control and monitoring. The Player expressly agrees, under penalty of criminal responsibility or civil liability, that it broadcasts messages are not likely to, without this list is exhaustive, including: * violate intellectual property rights of third parties: in this respect the Player undertakes not to reproduce or communicate publicly on the Site or the material protected under copyright, trademark filed as or more generally protected by other intellectual property rights held by third parties without the prior consent of the holders of such proprietary rights. * Contain computer viruses likely to interrupt, destroy or impair the functionality of the Site; * Being an apologist for crimes or contain illegal messages, threatening, or pedophile nature, pornographic, defamatory, obscene, hateful, racist, antisemitic, xenophobic, revisionist or contrary to public order or morality; * Infringe privacy or dignity of others; * Incite violence, fanaticism, crime, suicide, hatred due to religion, race, gender, sexual orientation, ethnicity, * Harass other players with whom the Player would be contacted when discussing the different communication areas of the site; * Promote or encourage any criminal activity or enterprise; * Solicit and / or disclose passwords and / or personal information for commercial or unlawful purposes; * Transmit any chain e-mails, unsolicited mass mailings, instant messages, commercials or unwanted unsolicited mail; * Contain advertisements and / or solicitations to offer products and / or commercial services through the Site. * Contain addresses or hypertext links to external sites whose content is contrary to the laws and regulations, which violate the rights of others or is contrary to these terms. 2) The Player agrees to hold only one account on BGA, unless otherwise approved by BGA. We reserve the right to terminate any multiple accounts attributable to the same person. 3) The Player agrees not to resort to the use of automated systems such as scripts to play or send messages. 4) The Player is solely responsible for keeping and confidentiality of their password and agrees not to communicate at any time whatsoever, his password to any other player or to use the account, the username and password of another Player. It also undertakes not to create multiple accounts. The Player guarantees the accuracy of information provided to BGA for purposes of registration and agrees to notify any subsequent changes. 5) The Player acknowledges that BGA reserves, in case his use of the site would be contrary to these Terms and generally applicable laws and regulatory provisions in force, to immediately and without notice of its deregistration Site services and / or blocking its access to the Site. 6) BGA reserves, assuming the Player would be responsible for an offense under the legislation or affect the rights of third parties the right to provide, upon request of all legitimate authority (courts, administrative authorities, police), all information allowing or facilitating the identification of the offending Player. 7) The Player is required to notify BGA, using the "Report this player" function, any misuse of the Site which he has knowledge, including any message whose contents violate the above prohibitions set or more generally applicable laws and regulatory provisions in force. == Privacy and Copyright Protection == BGA's [http://boardgamearena.com/#!doc/privacy privacy policies] explain how we treat your personal data and protect your privacy when you use our Services. By using our Services, you agree that BGA can use such data in accordance with our privacy policies. We respond to notices of alleged copyright infringement and terminate accounts of repeat infringers according to the process set out in France and the European Union. If you think somebody is violating your copyrights and want to notify us, you can contact us directly though our "Contact" section. BGA wishes to place a cookie on the computer of the subscriber. A cookie can not be personally identified. However, it records information relating to the navigation of the computer on the Site (pages viewed, date and time of visit, etc.). BGA that can read during subsequent visits. This will allow for easier navigation and avoid having to provide each new visit the information already sent an earlier date. It is stated that the shelf life of "cookies" BGA implanted is less than 6 (six) months. BGA notify the Player that the setting of their browser to alert you of the presence of "cookies" and that he may oppose the registration of "cookies". == Your Content in our Services == Some of our Services allow you to upload, submit, store, send or receive content. You retain ownership of any intellectual property rights that you hold in that content. In short, what belongs to you stays yours. When you upload, submit, store, send or receive content to or through our Services, you give BGA (and those we work with) a worldwide license to use, host, store, reproduce, modify, create derivative works (such as those resulting from translations, adaptations or other changes we make so that your content works better with our Services), communicate, publish, publicly perform, publicly display and distribute such content. The rights you grant in this license are for the limited purpose of operating, promoting, and improving our Services, and to develop new ones. This license continues even if you stop using our Services. Some Services may offer you ways to access and remove content that has been provided to that Service. Also, in some of our Services, there are terms or settings that narrow the scope of our use of the content submitted in those Services. Make sure you have the necessary rights to grant us this license for any content that you submit to our Services. Our automated systems analyze your content to provide you personally relevant features. This analysis occurs as the content is sent, received, and when it is stored. You can find more information about how BGA uses and stores content in the privacy policy or additional terms for particular Services. If you submit feedback or suggestions about our Services, we may use your feedback or suggestions without obligation to you. == About Software in our Services == When a Service requires or includes downloadable software, this software may update automatically on your device once a new version or feature is available. Some Services may let you adjust your automatic update settings. BGA gives you a personal, worldwide, royalty-free, non-assignable and non-exclusive license to use the software provided to you by BGA as part of the Services. This license is for the sole purpose of enabling you to use and enjoy the benefit of the Services as provided by BGA, in the manner permitted by these terms. You may not copy, modify, distribute, sell, or lease any part of our Services or included software, nor may you reverse engineer or attempt to extract the source code of that software, unless laws prohibit those restrictions or you have our written permission. Open source software is important to us. Some software used in our Services may be offered under an open source license that we will make available to you. There may be provisions in the open source license that expressly override some of these terms. == Modifying and Terminating our Services == We are constantly changing and improving our Services. We may add or remove functionalities or features, and we may suspend or stop a Service altogether. You can stop using our Services at any time, although we’ll be sorry to see you go. BGA may also stop providing Services to you, or add or create new limits to our Services at any time. We believe that you own your data and preserving your access to such data is important. If we discontinue a Service, where reasonably possible, we will give you reasonable advance notice and a chance to get information out of that Service. == Our Warranties and Disclaimers == We provide our Services using a commercially reasonable level of skill and care and we hope that you will enjoy using them. But there are certain things that we don’t promise about our Services. OTHER THAN AS EXPRESSLY SET OUT IN THESE TERMS OR ADDITIONAL TERMS, NEITHER BGA NOR ITS SUPPLIERS OR DISTRIBUTORS MAKE ANY SPECIFIC PROMISES ABOUT THE SERVICES. FOR EXAMPLE, WE DON’T MAKE ANY COMMITMENTS ABOUT THE CONTENT WITHIN THE SERVICES, THE SPECIFIC FUNCTIONS OF THE SERVICES, OR THEIR RELIABILITY, AVAILABILITY, OR ABILITY TO MEET YOUR NEEDS. WE PROVIDE THE SERVICES “AS IS”. SOME JURISDICTIONS PROVIDE FOR CERTAIN WARRANTIES, LIKE THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. TO THE EXTENT PERMITTED BY LAW, WE EXCLUDE ALL WARRANTIES. == Liability for our Services == WHEN PERMITTED BY LAW, BGA WILL NOT BE RESPONSIBLE FOR LOST PROFITS, REVENUES, OR DATA, FINANCIAL LOSSES OR INDIRECT, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES. TO THE EXTENT PERMITTED BY LAW, THE TOTAL LIABILITY OF BGA, AND ITS SUPPLIERS AND DISTRIBUTORS, FOR ANY CLAIMS UNDER THESE TERMS, INCLUDING FOR ANY IMPLIED WARRANTIES, IS LIMITED TO THE AMOUNT YOU PAID US TO USE THE SERVICES (OR, IF WE CHOOSE, TO SUPPLYING YOU THE SERVICES AGAIN). IN ALL CASES, BGA, AND ITS SUPPLIERS AND DISTRIBUTORS, WILL NOT BE LIABLE FOR ANY LOSS OR DAMAGE THAT IS NOT REASONABLY FORESEEABLE. == Business uses of our Services == If you are using our Services on behalf of a business, that business accepts these terms. It will hold harmless and indemnify BGA and its affiliates, officers, agents, and employees from any claim, suit or action arising from or related to the use of the Services or violation of these terms, including any liability or expense arising from claims, losses, damages, suits, judgments, litigation costs and attorneys’ fees. == About these Terms == We may modify these terms or any additional terms that apply to a Service to, for example, reflect changes to the law or changes to our Services. You should look at the terms regularly. Changes will be effective immediately. If you do not agree to the modified terms for a Service, you should discontinue your use of that Service. If there is a conflict between these terms and the additional terms, the additional terms will control for that conflict. These terms control the relationship between BGA and you. They do not create any third party beneficiary rights. If you do not comply with these terms, and we don’t take action right away, this doesn’t mean that we are giving up any rights that we may have (such as taking action in the future). If it turns out that a particular term is not enforceable, this will not affect any other terms. The laws of France will apply to any disputes arising out of or relating to these terms or the Services. All claims arising out of or relating to these terms or the Services will be litigated exclusively in the French courts. For information about how to contact BGA, please visit our [http://boardgamearena.com/#!doc/contact contact page]. b990f1d85eb9c6a56c8d37e4cc9fdefd1097c506 1207 1206 2014-08-29T13:43:35Z Sourisdudesert 1 Protected "[[TermsOfService]]" ([edit=sysop] (indefinite) [move=sysop] (indefinite)) wikitext text/x-wiki = Board Game Arena Terms of Service = == Welcome to BGA! == Thanks for using our services (“Services”). The Services are provided by Board Game Arena ("BGA"), located at G. Isabelli, 19 bd de la République, 92260 Fontenay-aux-Roses, France. By using our Services, you are agreeing to these terms. Please read them carefully. == Using our Services == You must follow any policies made available to you within the Services. Don’t misuse our Services. For example, don’t interfere with our Services or try to access them using a method other than the interface and the instructions that we provide. You may use our Services only as permitted by law, including applicable export and re-export control laws and regulations. We may suspend or stop providing our Services to you if you do not comply with our terms or policies or if we are investigating suspected misconduct. Using our Services does not give you ownership of any intellectual property rights in our Services or the content you access. You may not use content from our Services unless you obtain permission from its owner or are otherwise permitted by law. These terms do not grant you the right to use any branding or logos used in our Services. Don’t remove, obscure, or alter any legal notices displayed in or along with our Services. Our Services display some content that is not from BGA. This content is the sole responsibility of the entity that makes it available. We may review content to determine whether it is illegal or violates our policies, and we may remove or refuse to display content that we reasonably believe violates our policies or the law. But that does not necessarily mean that we review content, so please don’t assume that we do. In connection with your use of the Services, we may send you service announcements, administrative messages, and other information. You may opt out of some of those communications. == Your BGA Account == You may need a BGA Account in order to use some of our Services. You may create your own BGA Account, or your BGA Account may be assigned to you by an administrator, such as your employer or educational institution. If you are using a BGA Account assigned to you by an administrator, different or additional terms may apply and your administrator may be able to access or disable your account. To protect your BGA Account, keep your password confidential. You are responsible for the activity that happens on or through your BGA Account. Try not to reuse your BGA Account password on third-party applications. If you learn of any unauthorized use of your password or BGA Account, please change it immediately from your preferences. == Your responsibility as a BGA player ("the Player") == 1) The Player is solely responsible for any messages, content and information posted by him on the site since, in its capacity as host of the service considered here, under the provisions of French Law No. 2004 -575 of 21 June 2004 on confidence in the digital economy, BGA can not be responsible for the content posted or transmitted by Players on the Site and on which BGA exercises no control and monitoring. The Player expressly agrees, under penalty of criminal responsibility or civil liability, that it broadcasts messages are not likely to, without this list is exhaustive, including: * violate intellectual property rights of third parties: in this respect the Player undertakes not to reproduce or communicate publicly on the Site or the material protected under copyright, trademark filed as or more generally protected by other intellectual property rights held by third parties without the prior consent of the holders of such proprietary rights. * Contain computer viruses likely to interrupt, destroy or impair the functionality of the Site; * Being an apologist for crimes or contain illegal messages, threatening, or pedophile nature, pornographic, defamatory, obscene, hateful, racist, antisemitic, xenophobic, revisionist or contrary to public order or morality; * Infringe privacy or dignity of others; * Incite violence, fanaticism, crime, suicide, hatred due to religion, race, gender, sexual orientation, ethnicity, * Harass other players with whom the Player would be contacted when discussing the different communication areas of the site; * Promote or encourage any criminal activity or enterprise; * Solicit and / or disclose passwords and / or personal information for commercial or unlawful purposes; * Transmit any chain e-mails, unsolicited mass mailings, instant messages, commercials or unwanted unsolicited mail; * Contain advertisements and / or solicitations to offer products and / or commercial services through the Site. * Contain addresses or hypertext links to external sites whose content is contrary to the laws and regulations, which violate the rights of others or is contrary to these terms. 2) The Player agrees to hold only one account on BGA, unless otherwise approved by BGA. We reserve the right to terminate any multiple accounts attributable to the same person. 3) The Player agrees not to resort to the use of automated systems such as scripts to play or send messages. 4) The Player is solely responsible for keeping and confidentiality of their password and agrees not to communicate at any time whatsoever, his password to any other player or to use the account, the username and password of another Player. It also undertakes not to create multiple accounts. The Player guarantees the accuracy of information provided to BGA for purposes of registration and agrees to notify any subsequent changes. 5) The Player acknowledges that BGA reserves, in case his use of the site would be contrary to these Terms and generally applicable laws and regulatory provisions in force, to immediately and without notice of its deregistration Site services and / or blocking its access to the Site. 6) BGA reserves, assuming the Player would be responsible for an offense under the legislation or affect the rights of third parties the right to provide, upon request of all legitimate authority (courts, administrative authorities, police), all information allowing or facilitating the identification of the offending Player. 7) The Player is required to notify BGA, using the "Report this player" function, any misuse of the Site which he has knowledge, including any message whose contents violate the above prohibitions set or more generally applicable laws and regulatory provisions in force. == Privacy and Copyright Protection == BGA's [http://boardgamearena.com/#!doc/privacy privacy policies] explain how we treat your personal data and protect your privacy when you use our Services. By using our Services, you agree that BGA can use such data in accordance with our privacy policies. We respond to notices of alleged copyright infringement and terminate accounts of repeat infringers according to the process set out in France and the European Union. If you think somebody is violating your copyrights and want to notify us, you can contact us directly though our "Contact" section. BGA wishes to place a cookie on the computer of the subscriber. A cookie can not be personally identified. However, it records information relating to the navigation of the computer on the Site (pages viewed, date and time of visit, etc.). BGA that can read during subsequent visits. This will allow for easier navigation and avoid having to provide each new visit the information already sent an earlier date. It is stated that the shelf life of "cookies" BGA implanted is less than 6 (six) months. BGA notify the Player that the setting of their browser to alert you of the presence of "cookies" and that he may oppose the registration of "cookies". == Your Content in our Services == Some of our Services allow you to upload, submit, store, send or receive content. You retain ownership of any intellectual property rights that you hold in that content. In short, what belongs to you stays yours. When you upload, submit, store, send or receive content to or through our Services, you give BGA (and those we work with) a worldwide license to use, host, store, reproduce, modify, create derivative works (such as those resulting from translations, adaptations or other changes we make so that your content works better with our Services), communicate, publish, publicly perform, publicly display and distribute such content. The rights you grant in this license are for the limited purpose of operating, promoting, and improving our Services, and to develop new ones. This license continues even if you stop using our Services. Some Services may offer you ways to access and remove content that has been provided to that Service. Also, in some of our Services, there are terms or settings that narrow the scope of our use of the content submitted in those Services. Make sure you have the necessary rights to grant us this license for any content that you submit to our Services. Our automated systems analyze your content to provide you personally relevant features. This analysis occurs as the content is sent, received, and when it is stored. You can find more information about how BGA uses and stores content in the privacy policy or additional terms for particular Services. If you submit feedback or suggestions about our Services, we may use your feedback or suggestions without obligation to you. == About Software in our Services == When a Service requires or includes downloadable software, this software may update automatically on your device once a new version or feature is available. Some Services may let you adjust your automatic update settings. BGA gives you a personal, worldwide, royalty-free, non-assignable and non-exclusive license to use the software provided to you by BGA as part of the Services. This license is for the sole purpose of enabling you to use and enjoy the benefit of the Services as provided by BGA, in the manner permitted by these terms. You may not copy, modify, distribute, sell, or lease any part of our Services or included software, nor may you reverse engineer or attempt to extract the source code of that software, unless laws prohibit those restrictions or you have our written permission. Open source software is important to us. Some software used in our Services may be offered under an open source license that we will make available to you. There may be provisions in the open source license that expressly override some of these terms. == Modifying and Terminating our Services == We are constantly changing and improving our Services. We may add or remove functionalities or features, and we may suspend or stop a Service altogether. You can stop using our Services at any time, although we’ll be sorry to see you go. BGA may also stop providing Services to you, or add or create new limits to our Services at any time. We believe that you own your data and preserving your access to such data is important. If we discontinue a Service, where reasonably possible, we will give you reasonable advance notice and a chance to get information out of that Service. == Our Warranties and Disclaimers == We provide our Services using a commercially reasonable level of skill and care and we hope that you will enjoy using them. But there are certain things that we don’t promise about our Services. OTHER THAN AS EXPRESSLY SET OUT IN THESE TERMS OR ADDITIONAL TERMS, NEITHER BGA NOR ITS SUPPLIERS OR DISTRIBUTORS MAKE ANY SPECIFIC PROMISES ABOUT THE SERVICES. FOR EXAMPLE, WE DON’T MAKE ANY COMMITMENTS ABOUT THE CONTENT WITHIN THE SERVICES, THE SPECIFIC FUNCTIONS OF THE SERVICES, OR THEIR RELIABILITY, AVAILABILITY, OR ABILITY TO MEET YOUR NEEDS. WE PROVIDE THE SERVICES “AS IS”. SOME JURISDICTIONS PROVIDE FOR CERTAIN WARRANTIES, LIKE THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. TO THE EXTENT PERMITTED BY LAW, WE EXCLUDE ALL WARRANTIES. == Liability for our Services == WHEN PERMITTED BY LAW, BGA WILL NOT BE RESPONSIBLE FOR LOST PROFITS, REVENUES, OR DATA, FINANCIAL LOSSES OR INDIRECT, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES. TO THE EXTENT PERMITTED BY LAW, THE TOTAL LIABILITY OF BGA, AND ITS SUPPLIERS AND DISTRIBUTORS, FOR ANY CLAIMS UNDER THESE TERMS, INCLUDING FOR ANY IMPLIED WARRANTIES, IS LIMITED TO THE AMOUNT YOU PAID US TO USE THE SERVICES (OR, IF WE CHOOSE, TO SUPPLYING YOU THE SERVICES AGAIN). IN ALL CASES, BGA, AND ITS SUPPLIERS AND DISTRIBUTORS, WILL NOT BE LIABLE FOR ANY LOSS OR DAMAGE THAT IS NOT REASONABLY FORESEEABLE. == Business uses of our Services == If you are using our Services on behalf of a business, that business accepts these terms. It will hold harmless and indemnify BGA and its affiliates, officers, agents, and employees from any claim, suit or action arising from or related to the use of the Services or violation of these terms, including any liability or expense arising from claims, losses, damages, suits, judgments, litigation costs and attorneys’ fees. == About these Terms == We may modify these terms or any additional terms that apply to a Service to, for example, reflect changes to the law or changes to our Services. You should look at the terms regularly. Changes will be effective immediately. If you do not agree to the modified terms for a Service, you should discontinue your use of that Service. If there is a conflict between these terms and the additional terms, the additional terms will control for that conflict. These terms control the relationship between BGA and you. They do not create any third party beneficiary rights. If you do not comply with these terms, and we don’t take action right away, this doesn’t mean that we are giving up any rights that we may have (such as taking action in the future). If it turns out that a particular term is not enforceable, this will not affect any other terms. The laws of France will apply to any disputes arising out of or relating to these terms or the Services. All claims arising out of or relating to these terms or the Services will be litigated exclusively in the French courts. For information about how to contact BGA, please visit our [http://boardgamearena.com/#!doc/contact contact page]. b990f1d85eb9c6a56c8d37e4cc9fdefd1097c506 1209 1207 2014-08-31T14:28:39Z Een 3 wikitext text/x-wiki = Board Game Arena Terms of Service = == Welcome to BGA! == Thanks for using our services (“Services”). The Services are provided by Board Game Arena ("BGA"), located at G. Isabelli, 19 bd de la République, 92260 Fontenay-aux-Roses, France. By using our Services, you are agreeing to these terms. Please read them carefully. == Using our Services == You must follow any policies made available to you within the Services. Don’t misuse our Services. For example, don’t interfere with our Services or try to access them using a method other than the interface and the instructions that we provide. You may use our Services only as permitted by law, including applicable export and re-export control laws and regulations. We may suspend or stop providing our Services to you if you do not comply with our terms or policies or if we are investigating suspected misconduct. Using our Services does not give you ownership of any intellectual property rights in our Services or the content you access. You may not use content from our Services unless you obtain permission from its owner or are otherwise permitted by law. These terms do not grant you the right to use any branding or logos used in our Services. Don’t remove, obscure, or alter any legal notices displayed in or along with our Services. Our Services display some content that is not from BGA. This content is the sole responsibility of the entity that makes it available. We may review content to determine whether it is illegal or violates our policies, and we may remove or refuse to display content that we reasonably believe violates our policies or the law. But that does not necessarily mean that we review content, so please don’t assume that we do. In connection with your use of the Services, we may send you service announcements, administrative messages, and other information. You may opt out of some of those communications. == Your BGA Account == You may need a BGA Account in order to use some of our Services. You may create your own BGA Account, or your BGA Account may be assigned to you by an administrator, such as your employer or educational institution. If you are using a BGA Account assigned to you by an administrator, different or additional terms may apply and your administrator may be able to access or disable your account. To protect your BGA Account, keep your password confidential. You are responsible for the activity that happens on or through your BGA Account. Try not to reuse your BGA Account password on third-party applications. If you learn of any unauthorized use of your password or BGA Account, please change it immediately from your preferences. == Your responsibilities as a BGA player ("the Player") == The Player is solely responsible for any message, content and information posted by him on the site since, in its capacity as host of the service considered here, under the provisions of French Law No. 2004-575 of 21 June 2004 on confidence in the digital economy, BGA cannot be held responsible for the content posted or transmitted by Players on the Site and on which BGA exercises no control and monitoring. The Player expressly agrees, under penalty of criminal responsibility or civil liability, that the messages and content he will post on the Site are not likely to (without this list being exhaustive): * violate intellectual property rights of third parties: in this respect the Player undertakes not to reproduce or communicate publicly on the Site or the material protected under copyright, trademark filed as or more generally protected by other intellectual property rights held by third parties without the prior consent of the holders of such proprietary rights; * Contain computer viruses likely to interrupt, destroy or impair the functionality of the Site; * Being an apologist for crimes or contain illegal messages, threatening, or pedophile nature, pornographic, defamatory, obscene, hateful, racist, antisemitic, xenophobic, revisionist or contrary to public order or morality; * Infringe privacy or dignity of others; * Incite violence, fanaticism, crime, suicide, hatred due to religion, race, gender, sexual orientation, ethnicity; * Harass other players with whom the Player would be contacted when discussing the different communication areas of the site; * Promote or encourage any criminal activity or enterprise; * Solicit and / or disclose passwords and / or personal information for commercial or unlawful purposes; * Transmit any chain e-mails, unsolicited mass mailings, instant messages, commercials or unwanted unsolicited mail; * Contain advertisements and / or solicitations to offer products and / or commercial services through the Site; * Contain addresses or hypertext links to external sites whose content is contrary to the laws and regulations, which violate the rights of others or is contrary to these terms. The Player agrees to hold only one account on BGA, unless otherwise approved by BGA. We reserve the right to terminate any multiple accounts attributable to the same person. The Player agrees not to resort to the use of automated systems such as scripts to play or send messages. The Player is solely responsible for the keeping and confidentiality of their password and agrees not to communicate it to any other player or to use the account, the username and password of another Player. The Player guarantees the accuracy of information provided to BGA for purposes of registration and agrees to notify any subsequent changes. The Player acknowledges that BGA reserves, in case his use of the site would be contrary to these Terms or to generally applicable laws and regulatory provisions, the right to - immediately and without notice - deregister him from the Site services and / or to block his access to the Site. BGA reserves, assuming the Player would be responsible for an offense under the legislation or for affecting the rights of third parties, the right to provide, upon request of any legitimate authority (courts, administrative authorities, police), all information allowing or facilitating the identification of the offending Player. The Player is required to notify BGA, using the "Report this player" function, of any misuse of the Site of which he has knowledge, including any message whose contents violates the above prohibitions or more generally applicable laws and regulatory provisions. == Privacy and Copyright Protection == BGA's [http://boardgamearena.com/#!doc/privacy privacy policies] explain how we treat your personal data and protect your privacy when you use our Services. By using our Services, you agree that BGA can use such data in accordance with our privacy policies. We respond to notices of alleged copyright infringement and terminate accounts of repeat infringers according to the process set out in France and the European Union. If you think somebody is violating your copyrights and want to notify us, you can contact us directly though our "Contact" section. BGA uses cookies. Cookies are stored on the computer of the subscriber, to record information relating to the navigation of the computer on the Site (such as pages viewed, date and time of visit, etc.) that BGA can read during subsequent visits. This allows for easier navigation and avoids having to provide at each new visit information that was already sent at an earlier date. It is stated that the shelf life of "cookies" created by BGA is less than 6 (six) months. BGA notifies the Player that the settings of his browser allows him to be alerted of the presence of "cookies" and to disable the use of "cookies" should he want to do so. == Your Content in our Services == Some of our Services allow you to upload, submit, store, send or receive content. You retain ownership of any intellectual property rights that you hold in that content. In short, what belongs to you stays yours. When you upload, submit, store, send or receive content to or through our Services, you give BGA (and those we work with) a worldwide license to use, host, store, reproduce, modify, create derivative works (such as those resulting from translations, adaptations or other changes we make so that your content works better with our Services), communicate, publish, publicly perform, publicly display and distribute such content. The rights you grant in this license are for the limited purpose of operating, promoting, and improving our Services, and to develop new ones. This license continues even if you stop using our Services. Some Services may offer you ways to access and remove content that has been provided to that Service. Also, in some of our Services, there are terms or settings that narrow the scope of our use of the content submitted in those Services. Make sure you have the necessary rights to grant us this license for any content that you submit to our Services. Our automated systems analyze your content to provide you personally relevant features. This analysis occurs as the content is sent, received, and when it is stored. You can find more information about how BGA uses and stores content in the privacy policy or additional terms for particular Services. If you submit feedback or suggestions about our Services, we may use your feedback or suggestions without obligation to you. == About Software in our Services == When a Service requires or includes downloadable software, this software may update automatically on your device once a new version or feature is available. Some Services may let you adjust your automatic update settings. BGA gives you a personal, worldwide, royalty-free, non-assignable and non-exclusive license to use the software provided to you by BGA as part of the Services. This license is for the sole purpose of enabling you to use and enjoy the benefit of the Services as provided by BGA, in the manner permitted by these terms. You may not copy, modify, distribute, sell, or lease any part of our Services or included software, nor may you reverse engineer or attempt to extract the source code of that software, unless laws prohibit those restrictions or you have our written permission. Open source software is important to us. Some software used in our Services may be offered under an open source license that we will make available to you. There may be provisions in the open source license that expressly override some of these terms. == Modifying and Terminating our Services == We are constantly changing and improving our Services. We may add or remove functionalities or features, and we may suspend or stop a Service altogether. You can stop using our Services at any time, although we’ll be sorry to see you go. BGA may also stop providing Services to you, or add or create new limits to our Services at any time. We believe that you own your data and preserving your access to such data is important. If we discontinue a Service, where reasonably possible, we will give you reasonable advance notice and a chance to get information out of that Service. == Our Warranties and Disclaimers == We provide our Services using a commercially reasonable level of skill and care and we hope that you will enjoy using them. But there are certain things that we don’t promise about our Services. OTHER THAN AS EXPRESSLY SET OUT IN THESE TERMS OR ADDITIONAL TERMS, NEITHER BGA NOR ITS SUPPLIERS OR DISTRIBUTORS MAKE ANY SPECIFIC PROMISES ABOUT THE SERVICES. FOR EXAMPLE, WE DON’T MAKE ANY COMMITMENTS ABOUT THE CONTENT WITHIN THE SERVICES, THE SPECIFIC FUNCTIONS OF THE SERVICES, OR THEIR RELIABILITY, AVAILABILITY, OR ABILITY TO MEET YOUR NEEDS. WE PROVIDE THE SERVICES “AS IS”. SOME JURISDICTIONS PROVIDE FOR CERTAIN WARRANTIES, LIKE THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. TO THE EXTENT PERMITTED BY LAW, WE EXCLUDE ALL WARRANTIES. == Liability for our Services == WHEN PERMITTED BY LAW, BGA WILL NOT BE RESPONSIBLE FOR LOST PROFITS, REVENUES, OR DATA, FINANCIAL LOSSES OR INDIRECT, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES. TO THE EXTENT PERMITTED BY LAW, THE TOTAL LIABILITY OF BGA, AND ITS SUPPLIERS AND DISTRIBUTORS, FOR ANY CLAIMS UNDER THESE TERMS, INCLUDING FOR ANY IMPLIED WARRANTIES, IS LIMITED TO THE AMOUNT YOU PAID US TO USE THE SERVICES (OR, IF WE CHOOSE, TO SUPPLYING YOU THE SERVICES AGAIN). IN ALL CASES, BGA, AND ITS SUPPLIERS AND DISTRIBUTORS, WILL NOT BE LIABLE FOR ANY LOSS OR DAMAGE THAT IS NOT REASONABLY FORESEEABLE. == Business uses of our Services == If you are using our Services on behalf of a business, that business accepts these terms. It will hold harmless and indemnify BGA and its affiliates, officers, agents, and employees from any claim, suit or action arising from or related to the use of the Services or violation of these terms, including any liability or expense arising from claims, losses, damages, suits, judgments, litigation costs and attorneys’ fees. == About these Terms == We may modify these terms or any additional terms that apply to a Service to, for example, reflect changes to the law or changes to our Services. You should look at the terms regularly. Changes will be effective immediately. If you do not agree to the modified terms for a Service, you should discontinue your use of that Service. If there is a conflict between these terms and the additional terms, the additional terms will control for that conflict. These terms control the relationship between BGA and you. They do not create any third party beneficiary rights. If you do not comply with these terms, and we don’t take action right away, this doesn’t mean that we are giving up any rights that we may have (such as taking action in the future). If it turns out that a particular term is not enforceable, this will not affect any other terms. The laws of France will apply to any disputes arising out of or relating to these terms or the Services. All claims arising out of or relating to these terms or the Services will be litigated exclusively in the French courts. For information about how to contact BGA, please visit our [http://boardgamearena.com/#!doc/contact contact page]. 0acc3ff0f4e2107841df58f6fe767c0fa4740e65 Privacy 0 128 1208 905 2014-08-29T13:44:43Z Sourisdudesert 1 Protected "[[Privacy]]" ([edit=sysop] (indefinite) [move=sysop] (indefinite)) wikitext text/x-wiki To create an account, you need to provide an email, user name and password. You can also complete your player profile with some other data. We store this data. Yep. It would be pretty annoying for you to enter it each time you visit ;) If you are 'internet paranoid' and you never provide any website with accurate personal information, congratulations! You can skip this section. If you are not, congratulations! You can also skip this section which is intended only for 'internet paranoid' people anyway... It has been written for compliance with some social network authentication policy (take your bet, there is only two - oh, wait, if you are reading this you probably know). Well, to be fair, I could have left it empty too, the only check made by said social network being that the page exists. But, what would have been the fun in that? If you are still interested to read on some stuff instead of going straight to playing: * Your password is stored encrypted, but the usual precautionary measures apply. You should use a strong password and not use the same one that for sensitive websites. Some people would say never to use the same password, but this looks like excessive blunt force to the head, except for websites with very sensitive information. Shouldn't be the case on a gaming website, but hey, do as you please. * We don't share your email with third parties without your consent. Your consent may be implicit in some obvious cases (such as if you take part in a contest with prizes from a publisher, as it will be needed for the publisher to contact you to redeem the prize). * Your profile information is visible to other players, as well as your gaming history on the website. So, since anyone can create an account on the site, it should be considered public information. But if you use a pseudonym for your username, it shouldn't be easy to link it to your real identity (in case you would be worried about that). Hope this all sounds reasonable to you, and that you can now enjoy Board Game Arena without second thoughts! Cheers and doughnuts, The admins. 936ac1f56e7544f713799cdf86cc4e3b858babbf Gamehelptakenoko 0 104 1210 1022 2014-09-06T02:28:45Z Drstuey 3099 Formatting, add actions, and some other changes and additions wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Bamboo and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - "may" take two identical actions this turn * '''Storm''' - move panda to any plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Build plot''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a straight line and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a straight line and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective card''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Improvements can only be placed on plots with no bamboo. There can only be 1 improvement on a plot and once placed cannot be changed. To place an improvement as soon as the plot is placed, pick the improvement first. Irrigation channels must be between two plots. When a plot is irrigated for the first time it grows bamboo. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. The gardener grows bamboo on his plot and all adjacent irrigated plots of the same color. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. e9156f948d8a51595ec3ffbf05716f53c4f87fef 1211 1210 2014-09-06T02:33:35Z Drstuey 3099 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Bamboo and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to any plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a straight line and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a straight line and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Improvements can only be placed on plots with no bamboo. There can only be 1 improvement on a plot and once placed cannot be changed. To place an improvement as soon as the plot is placed, pick the improvement first. Irrigation channels must be between two plots. When a plot is irrigated for the first time it grows bamboo. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. The gardener grows bamboo on his plot and all adjacent irrigated plots of the same color. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. 9a5317e21c583cd4d43cdbe6b347104b0ce3dd12 1212 1211 2014-09-06T02:49:36Z Drstuey 3099 add list of objective cards, test table code wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Bamboo and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to any plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a straight line and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a straight line and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Improvements can only be placed on plots with no bamboo. There can only be 1 improvement on a plot and once placed cannot be changed. To place an improvement as soon as the plot is placed, pick the improvement first. Irrigation channels must be between two plots. When a plot is irrigated for the first time it grows bamboo. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. The gardener grows bamboo on his plot and all adjacent irrigated plots of the same color. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===List of objectives=== '''Plot Objectives''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. {| !Points!!Objective |-|2||Green Triangle |-|2||Green Straight |-|2||Green Curve |-|3||Green Diamond |-|3||Yellow Triangle |-|3||Yellow Straight |-|3||Yellow Curve |-|4||Yellow Diamond |-|4||Pink Triangle |-|4||Pink Straight |-|4||Pink Curve |-|5||Pink Diamond |-|3||Yellow/Green Diamond |-|4||Pink/Green Diamond |-|5||Yellow/Pink Diamond |} '''Gardener Objectives''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts '''Panda Objectives (15 total)''' * 2 Green - 2 points (x5 cards) * 2 Yellow - 2 pts (x4) * 2 Pink - 2 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 2 pts (x3) 4dcf2c9a10ec781035dc7fc319c12ad705d2db82 1213 1212 2014-09-06T02:50:56Z Drstuey 3099 /* List of objectives */ correct table code wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Bamboo and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to any plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a straight line and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a straight line and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Improvements can only be placed on plots with no bamboo. There can only be 1 improvement on a plot and once placed cannot be changed. To place an improvement as soon as the plot is placed, pick the improvement first. Irrigation channels must be between two plots. When a plot is irrigated for the first time it grows bamboo. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. The gardener grows bamboo on his plot and all adjacent irrigated plots of the same color. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===List of objectives=== '''Plot Objectives''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. {| !Points!!Objective |- |2||Green Triangle |- |2||Green Straight |- |2||Green Curve |- |3||Green Diamond |- |3||Yellow Triangle |- |3||Yellow Straight |- |3||Yellow Curve |- |4||Yellow Diamond |- |4||Pink Triangle |- |4||Pink Straight |- |4||Pink Curve |- |5||Pink Diamond |- |3||Yellow/Green Diamond |- |4||Pink/Green Diamond |- |5||Yellow/Pink Diamond |} '''Gardener Objectives''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts '''Panda Objectives (15 total)''' * 2 Green - 2 points (x5 cards) * 2 Yellow - 2 pts (x4) * 2 Pink - 2 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 2 pts (x3) 4ceea82fde024523e255b27923cec34cb438af28 1214 1213 2014-09-06T02:53:52Z Drstuey 3099 /* List of objectives */ remove table, don't feel it adds much wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Bamboo and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to any plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a straight line and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a straight line and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Improvements can only be placed on plots with no bamboo. There can only be 1 improvement on a plot and once placed cannot be changed. To place an improvement as soon as the plot is placed, pick the improvement first. Irrigation channels must be between two plots. When a plot is irrigated for the first time it grows bamboo. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. The gardener grows bamboo on his plot and all adjacent irrigated plots of the same color. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===List of objectives=== '''Plot Objectives''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts '''Gardener Objectives''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts '''Panda Objectives (15 total)''' * 2 Green - 2 points (x5 cards) * 2 Yellow - 2 pts (x4) * 2 Pink - 2 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 2 pts (x3) 4e2ebef20514ff171f4b42fb2156b6baa8914128 1235 1214 2014-10-12T09:31:48Z Drstuey 3099 correct points wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Bamboo and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to any plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a straight line and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a straight line and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Improvements can only be placed on plots with no bamboo. There can only be 1 improvement on a plot and once placed cannot be changed. To place an improvement as soon as the plot is placed, pick the improvement first. Irrigation channels must be between two plots. When a plot is irrigated for the first time it grows bamboo. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. The gardener grows bamboo on his plot and all adjacent irrigated plots of the same color. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===List of objectives=== '''Plot Objectives''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts '''Gardener Objectives''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts '''Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) 33dde48a28d14d33d17f928267428b4bbaaed48d Multipleaccounts 0 164 1215 1125 2014-09-15T05:20:56Z Ameliaangelrose 6458 /* Playing from the same IP */ wikitext text/x-wiki == The Main Rule == '''One BGA account = One person''' == Playing from the same IP == This is '''authorized''' to play at the same table from the same IP (internet address). The warning message "this player plays from the same internet address than another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game. If you want to play from the same internet address as another person: * The best option is not to play at the same table, or play at a table where you know everyone. * If you play with strangers, make them comfortable with the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner. When some of your opponents are playing from the same IP: * You may politely refuse to play with them. * You should be vigilant and check that they are not collaborating during the game. * You don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report. == Boosting your ELO by playing against yourself == This is the most stupid and useless thing to do on BGA. Why? Because this is very easy to detect, and because the penalty is: * all your secondary account are removed. * your primary account is reset to 1500 ELO for all games. Why this is so easy to detect: * When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO. * In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game. * In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account". * Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless. If you have a lot of time to spend, please try to get better at this game and please do not try to cheat. 3d7e8e650132c7b4c30bb8f70eb052e09560065d Help 0 4 1216 1153 2014-09-22T04:35:01Z Kartis 6364 /* Games */ Add link to Backgammon wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpeightmastersrevenge|8 Master's revenge]] * [[Gamehelpelfenland|Elfenland]] * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] </td> <td valign="top"> * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] </td> <td valign="top"> * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] </td> <td valign="top"> * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelpsechsnimmt|Take 5!]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] </td> <td valign="top"> * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> fa778e83a3c90ae568af77891b63757c21afc84d Gamehelptokaido 0 134 1217 1194 2014-09-27T13:32:33Z Jgbaxter 6455 /* Object of the game */ wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== '''Farm''' : The player earns 3 coins. '''Hot Spring''' : The player takes a Hot Spring card. These cards are worth 2 or 3 points. '''Temple''' : The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. '''Encounters''' : The player draws one Encounter card and receives a bonus: :* Shokunin - one Souvenir :* Annaibito - one Panorama :* Samurai - 3 points :* Kuge - 3 coins :* Miko - 1 point and 1 coin to the Temple (from the bank) '''Village''' : The player draws 3 Souvenir cards and can purchase one or more of these cards. : Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks. : Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection. : As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type. :* The first Souvenir in a set is worth 1 point. :* The second Souvenir in a set is worth 3 points. :* The third Souvenir in a set is worth 5 points. :* The fourth Souvenir in a set is worth 7 points. '''Panorama''' : Panoramas are made of 3, 4 or 5 sections. : When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ». : Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card. : '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy). '''Inns''' : All Travelers must stop at each Inn. : The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points. : The first traveler occupies the space nearest the road, and later travelers form a line after him. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. : He can then purchase one Meal card of his choice by paying its price. : He adds this card, face up, to his collection and places the remaining cards next to the board, face down. : He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards. : '''IMPORTANT:''' :* A traveler cannot taste the same culinary specialty twice during his journey. :* A traveler can never purchase more than one Meal card per Inn. :* A traveler is never obliged to purchase a Meal card. == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added. Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf Note: The Fortune die (for gambling at the farm) has these faces: x0, x1, x2, x3, x3, x4 == The New Encounters == This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large 16210282282797d012b9b1eef66f2d7cf40f0519 1218 1217 2014-09-27T13:34:48Z Jgbaxter 6455 /* Playing the game */ wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== '''Farm''' : The player earns 3 coins. '''Hot Spring''' : The player takes a Hot Spring card. These cards are worth 2 or 3 points. '''Temple''' : The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. '''Encounters''' : The player draws one Encounter card and receives a bonus: :* Shokunin - one Souvenir :* Annaibito - one Panorama :* Samurai - 3 points :* Kuge - 3 coins :* Miko - 1 point and 1 coin to the Temple (from the bank) '''Village''' : The player draws 3 Souvenir cards and can purchase one or more of these cards. : Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks. : Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection. : As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type. :* The first Souvenir in a set is worth 1 point. :* The second Souvenir in a set is worth 3 points. :* The third Souvenir in a set is worth 5 points. :* The fourth Souvenir in a set is worth 7 points. '''Panorama''' : Panoramas are made of 3, 4 or 5 sections. : When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ». : Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card. : '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy). '''Inns''' : All Travelers must stop at each Inn. : The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points. : The first traveler occupies the space nearest the road, and later travelers form a line after him. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. : He can then purchase one Meal card of his choice by paying its price. : He adds this card, face up, to his collection and places the remaining cards next to the board, face down. : He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards. : '''IMPORTANT:''' :* A traveler cannot taste the same culinary specialty twice during his journey. :* A traveler can never purchase more than one Meal card per Inn. :* A traveler is never obliged to purchase a Meal card. == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added. Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf Note: The Fortune die (for gambling at the farm) has these faces: x0, x1, x2, x3, x3, x4 == The New Encounters == This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large f1e65d8baf179846275274733491d332c6d192fc 1219 1218 2014-09-27T15:26:01Z Jgbaxter 6455 /* Description of the spaces */ changes pt1a wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' '''Farm''' :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X=Loses coins, 1= Recovers coins, 2/3/4= Gains double that many coins) '''Hot Springs''' :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4vp (counts for ''Bather'' accomplishment). '''Temple''' :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn vp. '''Encounters''' :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object an 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. '''Village''' : The player draws 3 Souvenir cards and can purchase one or more of these cards. : Each Souvenir belongs to one of 4 types: small objects, clothing, art, and food & drinks. : Souvenirs cost 1, 2 or 3 coins. They are worth 1, 3, 5 or 7 points depending on the actual Souvenirs in a player’s collection. : As you purchase Souvenir cards, group them into sets; each set can contain only one Souvenir of each type. :* The first Souvenir in a set is worth 1 point. :* The second Souvenir in a set is worth 3 points. :* The third Souvenir in a set is worth 5 points. :* The fourth Souvenir in a set is worth 7 points. :('''B''') :('''E''') '''Panorama''' : Panoramas are made of 3, 4 or 5 sections. : When a player stops on a Panorama Station, if he doesn’t yet have any Panorama cards of this type, he takes a Panorama card of value « 1 ». : Otherwise, he takes the next number in ascending order and scores a number of points equal to the value of the card. : '''NOTE:''' Each traveler can create only a single panorama of each type; a traveler who completes a panorama can no longer stop on the spaces corresponding to that type (Sea, Mountain, or Paddy). :('''B''') :('''E''') '''Inns''' : All Travelers must stop at each Inn. : The Inns are the places where players can buy Meal cards. Meal cards cost 1, 2 or 3 coins and all give 6 victory points. : The first traveler occupies the space nearest the road, and later travelers form a line after him. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. : He can then purchase one Meal card of his choice by paying its price. : He adds this card, face up, to his collection and places the remaining cards next to the board, face down. : He then must wait for the other travelers to arrive at the Inn. Upon arrival, each traveler can purchase one of the remaining Meal cards. :('''B''') :('''E''') : '''IMPORTANT:''' :* A traveler cannot taste the same culinary specialty twice during his journey. :* A traveler can never purchase more than one Meal card per Inn. :* A traveler is never obliged to purchase a Meal card. == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added. Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf Note: The Fortune die (for gambling at the farm) has these faces: x0, x1, x2, x3, x3, x4 == The New Encounters == This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large f3cec0e8b01af912f000c6f29a5650ad0493cb57 1220 1219 2014-09-27T16:33:41Z Jgbaxter 6455 /* Description of the spaces */ pt2 wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' '''Farm''' :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X=Loses coins, 1= Recovers coins, 2/3/4= Gains double that many coins) '''Hot Springs''' :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4vp (counts for ''Bather'' accomplishment). '''Temple''' :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn vp. '''Encounters''' :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object an 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. '''Village''' :('''B''') The player draws 3 Souvenir cards and can purchase 1-3 of these cards for 1-3 coins. There are four different Souvenirs and are grouped in sets. : The first Souvenir in each set is worth 1 point, the next is 3 points, then 5 and 7 points. :('''E''') Acquire a Legendary Object (counts for ''Collector'' accomplishment) for 1-3 coins: :* Shodo & Emaki - For 1 coin, immediately gain 1 point for each Souvenir or Legendary Object you have. Gain 1 point for each Souvenir thereafter. :* Buppatsu & Ema - For 2 coins, this counts as a different Souvenir type, 5 types in a set is worth 9 points. :* Murasame & Masamune - For 3 coins, gain 8 points. '''Panorama''' :('''B''') There are three Panorama types and are made of 3 (Field), 4 (Mountain) or 5 (Paddy) sections. : When a player stops on a Panorama they take the first Panorama of that type that they do not have (value from 1-5) and scores that many points. : Each traveler can create only a single panorama of each type and when completed can no longer stop on the spaces corresponding to that type. :('''E''') A player may instead take a Cherry Tree and gain 2 points and 1 coin. '''Inns''' : All Travelers must stop at each Inn, they may not leave until all players have arrived at that Inn. : The Inns allow players to buy one unique Meal card for 1-3 coins and are worth 6 points. A player may not have two of the same Meal cards. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. Then may buy one of those cards and leaving the others. : When acquired meals are add to the players collection face down. As other players arrive they may choose from the remaining cards. :* ''A traveler cannot taste the same culinary specialty twice during his journey.'' :* ''A traveler can never purchase more than one Meal card per Inn.'' :* ''A traveler is never obliged to purchase a Meal card.'' == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added. Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf Note: The Fortune die (for gambling at the farm) has these faces: x0, x1, x2, x3, x3, x4 == The New Encounters == This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large 5c67e6e1d8b6f15dc951b10bceed1526cdb95391 1221 1220 2014-09-28T05:28:04Z Jgbaxter 6455 /* Description of the spaces */ wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' '''Farm''' :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X=Loses coins, 1= Recovers coins, 2/3/4= Gains double that many coins) '''Hot Springs''' :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4vp (counts for ''Bather'' accomplishment). '''Temple''' :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn vp. '''Encounters''' :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - Pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object an 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. '''Village''' :('''B''') The player draws 3 Souvenir cards and can purchase 1-3 of these cards for 1-3 coins. There are four different Souvenirs and are grouped in sets. : The first Souvenir in each set is worth 1 point, the next is 3 points, then 5 and 7 points. :('''E''') Acquire a Legendary Object (counts for ''Collector'' accomplishment) for 1-3 coins: :* Shodo & Emaki - For 1 coin, immediately gain 1 point for each Souvenir or Legendary Object you have. Gain 1 point for each Souvenir thereafter. :* Buppatsu & Ema - For 2 coins, this counts as a different Souvenir type, 5 types in a set is worth 9 points. :* Murasame & Masamune - For 3 coins, gain 8 points. '''Panorama''' :('''B''') There are three Panorama types and are made of 3 (Field), 4 (Mountain) or 5 (Paddy) sections. : When a player stops on a Panorama they take the first Panorama of that type that they do not have (value from 1-5) and scores that many points. : Each traveler can create only a single panorama of each type and when completed can no longer stop on the spaces corresponding to that type. :('''E''') A player may instead take a Cherry Tree and gain 2 points and 1 coin. '''Inns''' : All Travelers must stop at each Inn, they may not leave until all players have arrived at that Inn. : The Inns allow players to buy one unique Meal card for 1-3 coins and are worth 6 points. A player may not have two of the same Meal cards. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. Then may buy one of those cards and leaving the others. : When acquired meals are add to the players collection face down. As other players arrive they may choose from the remaining cards. :* ''A traveler cannot taste the same culinary specialty twice during his journey.'' :* ''A traveler can never purchase more than one Meal card per Inn.'' :* ''A traveler is never obliged to purchase a Meal card.'' == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added. Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf Note: The Fortune die (for gambling at the farm) has these faces: x0, x1, x2, x3, x3, x4 == The New Encounters == This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large 9b3db0f6fd484e25f6dc8268dc78cef008484827 1222 1221 2014-09-28T05:29:33Z Jgbaxter 6455 /* Description of the spaces */ wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' '''Farm''' :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X=Loses coins, 1= Recovers coins, 2/3/4= Gains double that many coins) '''Hot Springs''' :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4 points (counts for ''Bather'' accomplishment). '''Temple''' :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn points. '''Encounters''' :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - Pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object an 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. '''Village''' :('''B''') The player draws 3 Souvenir cards and can purchase 1-3 of these cards for 1-3 coins. There are four different Souvenirs and are grouped in sets. : The first Souvenir in each set is worth 1 point, the next is 3 points, then 5 and 7 points. :('''E''') Acquire a Legendary Object (counts for ''Collector'' accomplishment) for 1-3 coins: :* Shodo & Emaki - For 1 coin, immediately gain 1 point for each Souvenir or Legendary Object you have. Gain 1 point for each Souvenir thereafter. :* Buppatsu & Ema - For 2 coins, this counts as a different Souvenir type, 5 types in a set is worth 9 points. :* Murasame & Masamune - For 3 coins, gain 8 points. '''Panorama''' :('''B''') There are three Panorama types and are made of 3 (Field), 4 (Mountain) or 5 (Paddy) sections. : When a player stops on a Panorama they take the first Panorama of that type that they do not have (value from 1-5) and scores that many points. : Each traveler can create only a single panorama of each type and when completed can no longer stop on the spaces corresponding to that type. :('''E''') A player may instead take a Cherry Tree and gain 2 points and 1 coin. '''Inns''' : All Travelers must stop at each Inn, they may not leave until all players have arrived at that Inn. : The Inns allow players to buy one unique Meal card for 1-3 coins and are worth 6 points. A player may not have two of the same Meal cards. : When the first traveler arrives at an Inn, he draws as many Meal cards as there are players, plus 1. Then may buy one of those cards and leaving the others. : When acquired meals are add to the players collection face down. As other players arrive they may choose from the remaining cards. :* ''A traveler cannot taste the same culinary specialty twice during his journey.'' :* ''A traveler can never purchase more than one Meal card per Inn.'' :* ''A traveler is never obliged to purchase a Meal card.'' == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added. Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf Note: The Fortune die (for gambling at the farm) has these faces: x0, x1, x2, x3, x3, x4 == The New Encounters == This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large 55004dc0a726f4747e1a18aa9d1798e073b8fe29 1223 1222 2014-09-28T15:07:44Z Jgbaxter 6455 /* Description of the spaces */ wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' '''Encounters''' :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - Pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object an 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. '''Farm''' :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X= Loses coins, 1= Recovers coins, 2/3/3/4= Gains double that many coins). '''Hot Springs''' :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4 points (counts for ''Bather'' accomplishment). '''Panorama''' :('''B''') There are three Panorama types and are made of 3 (Field), 4 (Mountain), or 5 (Paddy) sections. : When a player stops on a Panorama they take the first Panorama of that type that they do not have (value from 1-5) and scores that many points. Each traveler can create only a single panorama of each type and when completed can no longer stop on the spaces corresponding to that type. :('''E''') A player may instead take a Cherry Tree and gain 2 points and 1 coin. '''Temple''' :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn points. '''Village''' :('''B''') The player draws 3 Souvenir cards and can purchase 1-3 of these cards for 1-3 coins. There are four different Souvenirs and are grouped in sets. The first Souvenir in each set is worth 1 point, the next is 3 points, then 5 and 7 points. :('''E''') Acquire a Legendary Object (counts for ''Collector'' accomplishment) for 1-3 coins: :* Shodo & Emaki - For 1 coin, gain 1 point for each Souvenir or Legendary Object. Gain 1 point for each Souvenir thereafter. :* Buppatsu & Ema - For 2 coins this counts as a different Souvenir type, 5 types in a set is worth 9 points. :* Murasame & Masamune - For 3 coins, gain 8 points. '''Inns''' : All Travelers must stop at each Inn, they may not leave until all players have arrived at that Inn. : The Inns allow players to buy one unique Meal card for 1-3 coins that are worth 6 points. : When the first traveler arrives at an Inn, they draw as many Meal cards as there are players, plus 1. : As players arrive at the Inn they may buy a Meal card to add to their collection, hidden from other players. :* ''A traveler cannot taste the same culinary specialty twice during their journey.'' :* ''A traveler can never purchase more than one Meal card per Inn.'' :* ''A traveler is never obliged to purchase a Meal card.'' == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. ---- '''(Extracted from the English rule book)''' = Expansions = == Cross Roads Expansion == With this expansion, each station (except the Inn) gives travelers a new option. There are also new travelers added. Rules for playing the Cross Roads Expansion can be found here: http://www.funforge.fr/US/files/crossroads/Crossroads_Rules_US.pdf Note: The Fortune die (for gambling at the farm) has these faces: x0, x1, x2, x3, x3, x4 == The New Encounters == This expansion adds 4 new Encounter cards. Description of the cards is here: http://boardgamegeek.com/image/1452161/tokaido-the-new-encounters?size=large ae51b1e5161658a642841a54b9e17f17b5107fca 1224 1223 2014-09-28T15:10:50Z Jgbaxter 6455 incorporated into sections. wikitext text/x-wiki == Object of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' '''Encounters''' :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - Pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object an 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. '''Farm''' :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X= Loses coins, 1= Recovers coins, 2/3/3/4= Gains double that many coins). '''Hot Springs''' :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4 points (counts for ''Bather'' accomplishment). '''Panorama''' :('''B''') There are three Panorama types and are made of 3 (Field), 4 (Mountain), or 5 (Paddy) sections. : When a player stops on a Panorama they take the first Panorama of that type that they do not have (value from 1-5) and scores that many points. Each traveler can create only a single panorama of each type and when completed can no longer stop on the spaces corresponding to that type. :('''E''') A player may instead take a Cherry Tree and gain 2 points and 1 coin. '''Temple''' :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn points. '''Village''' :('''B''') The player draws 3 Souvenir cards and can purchase 1-3 of these cards for 1-3 coins. There are four different Souvenirs and are grouped in sets. The first Souvenir in each set is worth 1 point, the next is 3 points, then 5 and 7 points. :('''E''') Acquire a Legendary Object (counts for ''Collector'' accomplishment) for 1-3 coins: :* Shodo & Emaki - For 1 coin, gain 1 point for each Souvenir or Legendary Object. Gain 1 point for each Souvenir thereafter. :* Buppatsu & Ema - For 2 coins this counts as a different Souvenir type, 5 types in a set is worth 9 points. :* Murasame & Masamune - For 3 coins, gain 8 points. '''Inns''' : All Travelers must stop at each Inn, they may not leave until all players have arrived at that Inn. : The Inns allow players to buy one unique Meal card for 1-3 coins that are worth 6 points. : When the first traveler arrives at an Inn, they draw as many Meal cards as there are players, plus 1. : As players arrive at the Inn they may buy a Meal card to add to their collection, hidden from other players. :* ''A traveler cannot taste the same culinary specialty twice during their journey.'' :* ''A traveler can never purchase more than one Meal card per Inn.'' :* ''A traveler is never obliged to purchase a Meal card.'' == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. 0b2dcab0511de11fdb501d69f8432355d347cb7a 1226 1224 2014-10-07T16:42:42Z Jgbaxter 6455 toc wikitext text/x-wiki ==  Objective of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' ===Encounters=== :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - Pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object an 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. ===Farm=== :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X= Loses coins, 1= Recovers coins, 2/3/3/4= Gains double that many coins). ===Hot Springs=== :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4 points (counts for ''Bather'' accomplishment). ===Panorama=== :('''B''') There are three Panorama types and are made of 3 (Field), 4 (Mountain), or 5 (Paddy) sections. : When a player stops on a Panorama they take the first Panorama of that type that they do not have (value from 1-5) and scores that many points. Each traveler can create only a single panorama of each type and when completed can no longer stop on the spaces corresponding to that type. :('''E''') A player may instead take a Cherry Tree and gain 2 points and 1 coin. ===Temple=== :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn points. ===Village=== :('''B''') The player draws 3 Souvenir cards and can purchase 1-3 of these cards for 1-3 coins. There are four different Souvenirs and are grouped in sets. The first Souvenir in each set is worth 1 point, the next is 3 points, then 5 and 7 points. :('''E''') Acquire a Legendary Object (counts for ''Collector'' accomplishment) for 1-3 coins: :* Shodo & Emaki - For 1 coin, gain 1 point for each Souvenir or Legendary Object. Gain 1 point for each Souvenir thereafter. :* Buppatsu & Ema - For 2 coins this counts as a different Souvenir type, 5 types in a set is worth 9 points. :* Murasame & Masamune - For 3 coins, gain 8 points. ===Inns=== : All Travelers must stop at each Inn, they may not leave until all players have arrived at that Inn. : The Inns allow players to buy one unique Meal card for 1-3 coins that are worth 6 points. : When the first traveler arrives at an Inn, they draw as many Meal cards as there are players, plus 1. : As players arrive at the Inn they may buy a Meal card to add to their collection, hidden from other players. :* ''A traveler cannot taste the same culinary specialty twice during their journey.'' :* ''A traveler can never purchase more than one Meal card per Inn.'' :* ''A traveler is never obliged to purchase a Meal card.'' == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. 5e5d9a1fdd654f9a90a0f860d3be12c6f9c4ee19 Gamehelphive 0 167 1225 1164 2014-09-29T18:29:51Z Squarerootofthree 5668 Added expansion piece descriptions wikitext text/x-wiki Each turn, you may either place an insect or move an insect. All insects in play must be contiguous at all times. The first player's Queen Bee to be surrounded on all sides loses. You must place your Queen be by your fourth turn. Movement rules: * Queen Bee: Can only move one space * Beetle: Only one space, but it can move on top of another insect * Spider: 3 spaces in one direction * Grasshopper: Moves to the next open space in a straight line * Soldier Ant: It can move an unlimited amount along outside borders Expansion Pieces: * Mosquito: Uses the movement ability of any piece it is touching * Ladybug: Travels two spaces on top of other pieces and one space back down * Pill bug: Can move a single space, or move a piece currently adjacent to it to another adjacent location This is just a brief summary of movement rules. This has a comprehensive overview of movement rules: http://boardgamegeek.com/thread/371756/hive-detailed-review 3db6173830fa167002ea1529d8e4cbae4453b62c Gamehelpcheckers 0 171 1227 2014-10-07T17:15:04Z Jgbaxter 6455 start page wikitext text/x-wiki == Objective of the Game== Checkers, also known as 'draughts', is a timeless abstract strategy game for two players dating back almost a thousand years. In the game you move your pieces until you've jumped over all pieces of your opponent and have removed them from the board. Traditionally one player has light pieces and the other has dark pieces. ===How To Play=== Players move one piece diagonally at a time in alternating play (starting with light). All references to squares refer to the dark squares only. The board is an 8 by 8 square of squares in alternating light or dark colours. Players should set up pieces on the 12 dark squares in the first three rows closest to them (the light spaces are completely ignored in the game), setting up three rows of 4 checkers. ==Moving & Capturing== Take turns moving a checker one space diagonally forward towards the opponents side of the board on a square that contains no checkers of either player. You may 'jump' your opponents checkers by making a capturing move if your checker is located at most one space behind your opponent's checker (on your side). When capturing you jump over the checker moving two spaces in the same direction and then remove their piece from the game. Capturing multiple pieces using multiple jumps in the same turn is a key part of the game, when doing so you may change which direction they're going diagonally, but they must still always move forward. :* If you have the opportunity to jump your opponent's checker,you must. :* If you have the opportunity to jump a choice of opponent's checkers, you may chooce which but must capture one of them. :* If you're capturing a checker, you can still only move forward once though if there is another opportunity to capture then you continue capturing subsequent checkers until there are no more possible captures. ==Kings== When one of your pieces reaches the end of the opponent's board that piece is upgraded to a king, these may move in either direction now, backward to the players side or forward to the opponents side. :* Kings can still only move one diagonal space at a time unless capturing. :* Kings may move both forward and backward in the same turn when capturing. ==Winning== Complete ''one'' of the following three objectives; :* Capture all of an opponent's pieces. '''or''' :* Block all your opponent's pieces so they can't make any more moves. '''or''' :* Have all your pieces on the opponent's far end of the board (your opponent will need to have captured half or more of your pieces). 45f66b34be8a9f6fb23a31c90ae5c29b316a4c67 1228 1227 2014-10-07T17:16:03Z Jgbaxter 6455 /* Winning */ br wikitext text/x-wiki == Objective of the Game== Checkers, also known as 'draughts', is a timeless abstract strategy game for two players dating back almost a thousand years. In the game you move your pieces until you've jumped over all pieces of your opponent and have removed them from the board. Traditionally one player has light pieces and the other has dark pieces. ===How To Play=== Players move one piece diagonally at a time in alternating play (starting with light). All references to squares refer to the dark squares only. The board is an 8 by 8 square of squares in alternating light or dark colours. Players should set up pieces on the 12 dark squares in the first three rows closest to them (the light spaces are completely ignored in the game), setting up three rows of 4 checkers. ==Moving & Capturing== Take turns moving a checker one space diagonally forward towards the opponents side of the board on a square that contains no checkers of either player. You may 'jump' your opponents checkers by making a capturing move if your checker is located at most one space behind your opponent's checker (on your side). When capturing you jump over the checker moving two spaces in the same direction and then remove their piece from the game. Capturing multiple pieces using multiple jumps in the same turn is a key part of the game, when doing so you may change which direction they're going diagonally, but they must still always move forward. :* If you have the opportunity to jump your opponent's checker,you must. :* If you have the opportunity to jump a choice of opponent's checkers, you may chooce which but must capture one of them. :* If you're capturing a checker, you can still only move forward once though if there is another opportunity to capture then you continue capturing subsequent checkers until there are no more possible captures. ==Kings== When one of your pieces reaches the end of the opponent's board that piece is upgraded to a king, these may move in either direction now, backward to the players side or forward to the opponents side. :* Kings can still only move one diagonal space at a time unless capturing. :* Kings may move both forward and backward in the same turn when capturing. ==Winning== Complete ''one'' of the following three objectives; :* Capture all of an opponent's pieces. '''or''' :* Block all your opponent's pieces so they can't make any more moves. '''or''' :* Have all your pieces on the opponent's far end of the board (your opponent will need to have captured half or more of your pieces). 153b917f393b5ae02e4ca888fe9591bfe5b4df6d 1229 1228 2014-10-07T17:21:23Z Jgbaxter 6455 tweaks wikitext text/x-wiki == Objective of the Game== Checkers, also known as 'draughts', is a timeless abstract strategy game for two players dating back almost a thousand years. In the game you move your pieces until you've jumped over all pieces of your opponent and have removed them from the board. Players move one piece diagonally at a time in alternating play (starting with light). All references to squares refer to the dark squares only. The board is an 8 by 8 square of squares in alternating light or dark colours. Players should set up pieces on the 12 dark squares in the first three rows closest to them (the light spaces are completely ignored in the game), setting up three rows of 4 checkers. ==Moving & Capturing== Take turns moving a checker one space diagonally forward towards the opponent's side of the board on a square that contains no checkers of either player. You may 'jump' your opponents checkers by making a capturing move if your checker is located at most one space behind your opponent's checker (on your side). When capturing you jump over the checker moving two spaces in the same direction and then remove their piece from the game. Capturing multiple pieces using multiple jumps in the same turn is a key part of the game, when doing so you may change which direction they're moving diagonally, but they must still always move forward. :* If you have the opportunity to jump your opponent's checker, you must. :* You may continue capturing subsequent checkers until there are no more possible captures. :* If you have the opportunity to jump a choice of opponent's checkers, you may choose which but must capture one of them. ==Kings== When one of your pieces reaches the end of the opponent's board that piece is upgraded to a king, these may move in either direction now. :* Kings may move forward or backward diagonally. :* Kings can still only move one diagonal space at a time unless capturing. :* Kings may move both forward and backward in the same turn when capturing. ==Winning== Complete ''one'' of the following three objectives; :* Capture all of an opponent's pieces. '''or''' :* Block all your opponent's pieces so they can't make any more moves. '''or''' :* Have all your pieces on the opponent's far end of the board (your opponent will need to have captured half or more of your pieces). e4b034a0a52a4d96f4db254314377fca23a1d512 1230 1229 2014-10-07T17:33:29Z Jgbaxter 6455 strat wikitext text/x-wiki == Objective of the Game== Checkers, also known as 'draughts', is a timeless abstract strategy game for two players dating back almost a thousand years. In the game you move your pieces until you've jumped over all pieces of your opponent and have removed them from the board. Players move one piece diagonally at a time in alternating play (starting with light). All references to squares refer to the dark squares only. The board is an 8 by 8 square of squares in alternating light or dark colours. Players should set up pieces on the 12 dark squares in the first three rows closest to them (the light spaces are completely ignored in the game), setting up three rows of 4 checkers. ==Moving & Capturing== Take turns moving a checker one space diagonally forward towards the opponent's side of the board on a square that contains no checkers of either player. You may 'jump' your opponents checkers by making a capturing move if your checker is located at most one space behind your opponent's checker (on your side). When capturing you jump over the checker moving two spaces in the same direction and then remove their piece from the game. Capturing multiple pieces using multiple jumps in the same turn is a key part of the game, when doing so you may change which direction they're moving diagonally, but they must still always move forward. :* If you have the opportunity to jump your opponent's checker, you must. :* You may continue capturing subsequent checkers until there are no more possible captures. :* If you have the opportunity to jump a choice of opponent's checkers, you may choose which but must capture one of them. ==Kings== When one of your pieces reaches the end of the opponent's board that piece is upgraded to a king, these may move in either direction now. :* Kings may move forward or backward diagonally. :* Kings can still only move one diagonal space at a time unless capturing. :* Kings may move both forward and backward in the same turn when capturing. ==Winning== Complete ''one'' of the following three objectives; :* Capture all of an opponent's pieces. '''or''' :* Block all your opponent's pieces so they can't make any more moves. '''or''' :* Have all your pieces on the opponent's far end of the board (your opponent will need to have captured half or more of your pieces). ==Strategy== :* Be aggressive, you are more likely to win. Playing to the board sides are safer though without reward. :* Forward- always forward, it's alright to lose pieces as long as you take the opponent's, save your kings. :* Safety in numbers, don't leave your pieces alone, move them one after another in small groups to protect them. :* Protect the rear, protect forward or don't move your end row pieces as long as possible to prevent opponent's kings. :* Sacrifice when needed. draw out your opponent so you can get 2-1 trades the following turn, don't expose your kings without reward. :* Each king you get is a huge bonus, try to get as many as possible and don't waste them, sacrificing several pieces for a king can be alright. :* Don't forget to block your opponent when possible, you make not only that piece vulnerable but fail to protect it with a counter and give your opponent the chance to take multiple of your pieces in one turn. fc2c86647d235f973c91b506259e36d16a3893be 1231 1230 2014-10-07T17:39:00Z Jgbaxter 6455 draws wikitext text/x-wiki == Objective of the Game== Checkers, also known as 'draughts', is a timeless abstract strategy game for two players dating back almost a thousand years. In the game you move your pieces until you've jumped over all pieces of your opponent and have removed them from the board. Players move one piece diagonally at a time in alternating play (starting with light). All references to squares refer to the dark squares only. The board is an 8 by 8 square of squares in alternating light or dark colours. Players should set up pieces on the 12 dark squares in the first three rows closest to them (the light spaces are completely ignored in the game), setting up three rows of 4 checkers. ==Moving & Capturing== Take turns moving a checker one space diagonally forward towards the opponent's side of the board on a square that contains no checkers of either player. You may 'jump' your opponents checkers by making a capturing move if your checker is located at most one space behind your opponent's checker (on your side). When capturing you jump over the checker moving two spaces in the same direction and then remove their piece from the game. Capturing multiple pieces using multiple jumps in the same turn is a key part of the game, when doing so you may change which direction they're moving diagonally, but they must still always move forward. :* If you have the opportunity to jump your opponent's checker, you must. :* You may continue capturing subsequent checkers until there are no more possible captures. :* If you have the opportunity to jump a choice of opponent's checkers, you may choose which but must capture one of them. ==Kings== When one of your pieces reaches the end of the opponent's board that piece is upgraded to a king, these may move in either direction now. :* Kings may move forward or backward diagonally. :* Kings can still only move one diagonal space at a time unless capturing. :* Kings may move both forward and backward in the same turn when capturing. ==Winning== Complete ''one'' of the following three objectives; :* Capture all of an opponent's pieces. '''or''' :* Block all your opponent's pieces so they can't make any more moves. '''or''' :* Have all your pieces on the opponent's far end of the board (your opponent will need to have captured half or more of your pieces). ==Draws== A draw is declared if ''any'' of these conditions occur; :* A game is a draw if neither opponent has the possibility to win the game. '''or''' * The game is considered a draw when the same situation repeats itself for the third time (not necessarily consecutive). '''or''' * A one king against one king endgame is often declared a draw. ==Strategy== :* Be aggressive, you are more likely to win. Playing to the board sides are safer though without reward. :* Forward- always forward, it's alright to lose pieces as long as you take the opponent's, save your kings. :* Safety in numbers, don't leave your pieces alone, move them one after another in small groups to protect them. :* Protect the rear, protect forward or don't move your end row pieces as long as possible to prevent opponent's kings. :* Sacrifice when needed. draw out your opponent so you can get 2-1 trades the following turn, don't expose your kings without reward. :* Each king you get is a huge bonus, try to get as many as possible and don't waste them, sacrificing several pieces for a king can be alright. :* Don't forget to block your opponent when possible, you make not only that piece vulnerable but fail to protect it with a counter and give your opponent the chance to take multiple of your pieces in one turn. b19a1cd0daed511854e2b48fbbd6ee38038eda44 1232 1231 2014-10-07T17:39:32Z Jgbaxter 6455 /* Draws */ tab wikitext text/x-wiki == Objective of the Game== Checkers, also known as 'draughts', is a timeless abstract strategy game for two players dating back almost a thousand years. In the game you move your pieces until you've jumped over all pieces of your opponent and have removed them from the board. Players move one piece diagonally at a time in alternating play (starting with light). All references to squares refer to the dark squares only. The board is an 8 by 8 square of squares in alternating light or dark colours. Players should set up pieces on the 12 dark squares in the first three rows closest to them (the light spaces are completely ignored in the game), setting up three rows of 4 checkers. ==Moving & Capturing== Take turns moving a checker one space diagonally forward towards the opponent's side of the board on a square that contains no checkers of either player. You may 'jump' your opponents checkers by making a capturing move if your checker is located at most one space behind your opponent's checker (on your side). When capturing you jump over the checker moving two spaces in the same direction and then remove their piece from the game. Capturing multiple pieces using multiple jumps in the same turn is a key part of the game, when doing so you may change which direction they're moving diagonally, but they must still always move forward. :* If you have the opportunity to jump your opponent's checker, you must. :* You may continue capturing subsequent checkers until there are no more possible captures. :* If you have the opportunity to jump a choice of opponent's checkers, you may choose which but must capture one of them. ==Kings== When one of your pieces reaches the end of the opponent's board that piece is upgraded to a king, these may move in either direction now. :* Kings may move forward or backward diagonally. :* Kings can still only move one diagonal space at a time unless capturing. :* Kings may move both forward and backward in the same turn when capturing. ==Winning== Complete ''one'' of the following three objectives; :* Capture all of an opponent's pieces. '''or''' :* Block all your opponent's pieces so they can't make any more moves. '''or''' :* Have all your pieces on the opponent's far end of the board (your opponent will need to have captured half or more of your pieces). ==Draws== A draw is declared if ''any'' of these conditions occur; :* A game is a draw if neither opponent has the possibility to win the game. '''or''' :* The game is considered a draw when the same situation repeats itself for the third time (not necessarily consecutive). '''or''' :* A one king against one king endgame is often declared a draw. ==Strategy== :* Be aggressive, you are more likely to win. Playing to the board sides are safer though without reward. :* Forward- always forward, it's alright to lose pieces as long as you take the opponent's, save your kings. :* Safety in numbers, don't leave your pieces alone, move them one after another in small groups to protect them. :* Protect the rear, protect forward or don't move your end row pieces as long as possible to prevent opponent's kings. :* Sacrifice when needed. draw out your opponent so you can get 2-1 trades the following turn, don't expose your kings without reward. :* Each king you get is a huge bonus, try to get as many as possible and don't waste them, sacrificing several pieces for a king can be alright. :* Don't forget to block your opponent when possible, you make not only that piece vulnerable but fail to protect it with a counter and give your opponent the chance to take multiple of your pieces in one turn. cf37197bd4585d52712d1d109ddd75afae4d9cbb 1233 1232 2014-10-07T21:42:09Z Een 3 /*  Objective of the Game */ wikitext text/x-wiki == Objective of the Game == Checkers, also known as 'draughts', is a timeless abstract strategy game for two players dating back almost a thousand years. In the game you move your pieces until you've jumped over all pieces of your opponent and have removed them from the board. Players move one piece diagonally at a time in alternating play (starting with light). All references to squares refer to the dark squares only. The board is an 8 by 8 square of squares in alternating light or dark colours. Players should set up pieces on the 12 dark squares in the first three rows closest to them (the light spaces are completely ignored in the game), setting up three rows of 4 checkers. ==Moving & Capturing== Take turns moving a checker one space diagonally forward towards the opponent's side of the board on a square that contains no checkers of either player. You may 'jump' your opponents checkers by making a capturing move if your checker is located at most one space behind your opponent's checker (on your side). When capturing you jump over the checker moving two spaces in the same direction and then remove their piece from the game. Capturing multiple pieces using multiple jumps in the same turn is a key part of the game, when doing so you may change which direction they're moving diagonally, but they must still always move forward. :* If you have the opportunity to jump your opponent's checker, you must. :* You may continue capturing subsequent checkers until there are no more possible captures. :* If you have the opportunity to jump a choice of opponent's checkers, you may choose which but must capture one of them. ==Kings== When one of your pieces reaches the end of the opponent's board that piece is upgraded to a king, these may move in either direction now. :* Kings may move forward or backward diagonally. :* Kings can still only move one diagonal space at a time unless capturing. :* Kings may move both forward and backward in the same turn when capturing. ==Winning== Complete ''one'' of the following three objectives; :* Capture all of an opponent's pieces. '''or''' :* Block all your opponent's pieces so they can't make any more moves. '''or''' :* Have all your pieces on the opponent's far end of the board (your opponent will need to have captured half or more of your pieces). ==Draws== A draw is declared if ''any'' of these conditions occur; :* A game is a draw if neither opponent has the possibility to win the game. '''or''' :* The game is considered a draw when the same situation repeats itself for the third time (not necessarily consecutive). '''or''' :* A one king against one king endgame is often declared a draw. ==Strategy== :* Be aggressive, you are more likely to win. Playing to the board sides are safer though without reward. :* Forward- always forward, it's alright to lose pieces as long as you take the opponent's, save your kings. :* Safety in numbers, don't leave your pieces alone, move them one after another in small groups to protect them. :* Protect the rear, protect forward or don't move your end row pieces as long as possible to prevent opponent's kings. :* Sacrifice when needed. draw out your opponent so you can get 2-1 trades the following turn, don't expose your kings without reward. :* Each king you get is a huge bonus, try to get as many as possible and don't waste them, sacrificing several pieces for a king can be alright. :* Don't forget to block your opponent when possible, you make not only that piece vulnerable but fail to protect it with a counter and give your opponent the chance to take multiple of your pieces in one turn. d21283f4ef7e35c5aadcfe6542ea31efb8957cd3 About Board Game Arena 0 5 1234 28 2014-10-11T09:57:05Z Een 3 wikitext text/x-wiki With '''Board Game Arena''' you can play board games online with the whole world. Board Game Arena is a next generation game platform which makes online gaming more simple and attractive: * Nothing to install: play straight from your browser, from anywhere, at anytime. * Real time: your opponents are online, you play "live". * Simple: if you know the game, then you know how to play online. * Free. Board Game Arena offers a [http://en.boardgamearena.com/#!gamelist growing selection of board and card games]. We are specialized in modern adults games ("European style games"). This game platform has been designed to host any kind of game. This flexibility allow us to propose a '''new game every month'''. f6d6628c6fc827400541a322aee9882d130e8d1d 1246 1234 2014-10-15T00:54:44Z Wickedbad 6510 wikitext text/x-wiki With '''Board Game Arena''' you can play board games online with the whole world. Board Game Arena is a next generation game platform which makes online gaming more simple and attractive: * Nothing to install: play straight from your browser, from anywhere, at anytime. * Real time: your opponents are online, you play "live". * Simple: if you know the game, then you know how to play online. * Free. Board Game Arena offers a [http://en.boardgamearena.com/#!gamelist growing selection of board and card games]. We specialize in modern adults games ("European style games"). This game platform has been designed to host any kind of game. This flexibility allows us to offer a '''new game every month'''. 2de0f5d3a144cbeb42be99a80508455344bc36b2 Implijer:Wickedbad 2 172 1236 2014-10-15T00:16:08Z Wickedbad 6510 Created page with "Growing the Quoridor community. http://quoridorstrats.wordpress.com/ http://worldquoridorg.wordpress.com/" wikitext text/x-wiki Growing the Quoridor community. http://quoridorstrats.wordpress.com/ http://worldquoridorg.wordpress.com/ 8c0e50a501263f7a5b6f54f56f0ee5177c142e71 Faq 0 3 1237 1165 2014-10-15T00:19:26Z Wickedbad 6510 /* What do you mean by "real time play"? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used to differentiate against "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move, you are notified that it is your turn (via email or visiting the site). You then go to your game, take your turn, and the process repeats for another player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his allotted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. f89881317f64c7158d0a77c669d256ef2de34cfd 1238 1237 2014-10-15T00:22:10Z Wickedbad 6510 /* What is "turn based play"? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this thing possible, we are using the very latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his allotted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. 5b3ededddf59863f794d1ddd21ef32a49f94cadf 1239 1238 2014-10-15T00:22:52Z Wickedbad 6510 /* What do I need to play? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena proposes a various selection of board and card games, but is specialized in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his allotted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. 78603233167934bb045ee89cc8c073116826b239 1240 1239 2014-10-15T00:23:44Z Wickedbad 6510 /* What are the games available on BGA? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues one can encounter on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his allotted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. cdf96e89c3995abccf62ea1fa1616bf210c44e35 1241 1240 2014-10-15T00:25:02Z Wickedbad 6510 /* What can I do if I have an issue with the website? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there is only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who dream to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their players community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his allotted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. 2be120be9b152d9c49ae8f4d1c5508733b3668e4 1242 1241 2014-10-15T00:26:45Z Wickedbad 6510 /* I'm a game publisher: why would I like to have my game on Board Game Arena? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates game boxes sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his allotted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. eb3a69c9c27f3902ff4aca76c6a9bf13bc0f95fd 1243 1242 2014-10-15T00:28:40Z Wickedbad 6510 /* I'm a game publisher: why would I like to have my game on Board Game Arena? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity, it is still a young website. For the most popular games, you can find players at any time of the day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his allotted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. 4b556ad8651ce572511c9f6adb393656233717e7 1244 1243 2014-10-15T00:29:52Z Wickedbad 6510 /* I launched a new table but nobody is joining? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity it is still a young website. For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about is next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he is running out of time on the game clock for the current move (red bar) or if he goes over his allotted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. 6d910893b097f466b0facb819a9fb664ab6b4417 1245 1244 2014-10-15T00:49:28Z Wickedbad 6510 /* A player has to make a move but he/she doesn't. What can I do? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== Although Board Game Arena has been enjoying a growing popularity it is still a young website. For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he has run out of time on the game clock for the current move (red bar) or if he goes over his allotted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. c39566db961ccc56d55fff4db8e51bec2dcedbf3 Gamehelpinjawara 0 173 1247 2014-10-15T18:55:59Z Adela82 4198 Created page with " == AIM OF THE GAME == The aim of the INJAWARA board game is to work in team cooperatively and contribute to solve at least 1 Challenge related to each Millennium Development..." wikitext text/x-wiki == AIM OF THE GAME == The aim of the INJAWARA board game is to work in team cooperatively and contribute to solve at least 1 Challenge related to each Millennium Development Goal and 1 for each Region by moving the needed resources through the six regions and reply to questions related to the Challenges faced. The longer you ignore a problem, the more it will get worse! If a problem becomes too serious it will become impossible to solve it, and you will lose all. == THE GAME == The INJAWARA board game has no player turns, but in each round, all players, as a team, must decide the action to do. How decisions are taken must be agreed by all players at the beginning of the game. Every round has two phases: === 1. DO AN ACTION === The team must decide to make one of the following actions: ==== A. TRY TO SOLVE A CHALLENGE ==== Every challenge token has three data items: The region where it appears, the MDG affected by it, and the needed resource to solve it. If in the moment to choose an action, the convenient resource is on the same region than a challenge which needs it, the team my try to solve the challenge. A question associated to that MDG will be asked. ''If you answer correctly'', move forward the score marker associated to the MDG indicated by the challeng three boxes towards a higher score. It's not possible to move an score token beyond 100 points. If the score marker shows an X, turn it upside down to see the green tick. In the same manner, turn the region marker, where the challenge is located, upside down, if it wasn't showing the green tick yet. Likewise, if the resource was 'locked', turn it upside down, in order to unlock its power. The challenge token is discarded and place it in the discarded pile, marked with an X on the board. ''If you answer incorrectly'', don't move any marker or token. ''In both cases'', leave the question card on the discard pile, marked with an X, next to que question mark on the board. Place it with the questions facing up. ==== B. MOVE A RESOURCE TO AN ADJACENT REGION ==== All regions are linked between them, indicated by the black arrows on the board. You can move one resource from one region to another linked region, as an action. If by moving a resource to a region, in this region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ==== C. USE AN UNLOCKED RESOURCE POWER ==== If a resource has its power unlocked, you can use its power and turn that resource upside down (then you lock its power again). All powers are the following: ===== Economic resources ===== Swap places of two resources on the board. Economic resources may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Professionals ===== Move a resource to any region on the board. Professionals may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Materials ===== . Move towards higher score one box the score token of one of the following MDGS: 1, 2, 6, 7. ===== Politics ===== Move towards higher score one box the score token of one of the following MDGS: 3, 4, 5, 8. ===== Justice ===== You can discard a challenge token placed in any region, but it's not treated as solved. ===== Education ===== This is the only power that cant't be used in '1. Do an action' phase, but you can use it immediatly after you answer incorrectly a question. You can ask a second question to try to solve that challenge. === 2. A NEW CHALLENGE APPEARS === The challenge we left in the space marked by an eye on the board, is the next challenge that will appear in the game. Grab that challenge and place it on the region indicated by the leaf shape. In that moment, if in that region there was any other unsolved challenges, move one box towards a lower score, on the score board, all MDGs markers present in this region's challenges, without counting on th new challenge. ==== '-1' TOKEN ==== If the next challenge token is a'-1' one, check all unsolved challenges on the board and move one box towards a lower score, on the score board, all MDGs markeres present. Only one box may be moved per MDG, so ignore other challenges that references the same MDG. In that moment, grab all tokens from discarded challenges pile (marked with an X on the board) and the '-1' token and put them back into the bag. Grab a new challenge token from the bag, randomly, and place it on the space marked with an eye. Now you know which is the challenge for the next round. == END OF THE GAME == There are two possible scenarios when the game ends: 1. ''The team loses the game'', if in any moment of the game, any MDG score marker reaches the skull. If you want to calculate your final score, see the "Scoring. If we lose." section below. 2. ''The team wins the game'', if in any moment of the game, all MDG score markers show the green tick and all region markers show the green tick as well. If this situation occurs in the middle of several challenges solving, you can end solving up all of them (and also use the Education power, if this is unlocked). == SCORING == === If we lose === If our team has lost the game, move towards a lower score, all MDG markers, 3 boxes. If any of the markers reaches the skull, it cannot be moved beyond. Then, sum up all the scores, knowing the skull scores 0 points. === If we won === Sum up all scores of all MDGs markers and this will be your final score. (On the score board you can see an aid for suming up to three markers on the same score box, on grey). 6ae4153e87f51d0d2b4d45538485bed54a206ee3 1248 1247 2014-10-17T16:32:00Z Lennon 5509 /* AIM OF THE GAME */ wikitext text/x-wiki == このゲームの目的 == ボードゲーム・INJAWARAの目的はチームで協力し、各MDGに関連する少なくともひとつの課題を解決するために貢献をすることです。 そして、各6領域にひとつづつのリソースを移動させることにより、直面した課題に関連する問題に答えることです。 長い間問題を放置しておくことはよくありません。多くはより悪い方向に向かいます! 問題があまりにも深刻になりすぎた場合、あなたが問題を解決することは不可能となります。 そしてあなたは何もかも失うことになります... == THE GAME == The INJAWARA board game has no player turns, but in each round, all players, as a team, must decide the action to do. How decisions are taken must be agreed by all players at the beginning of the game. Every round has two phases: === 1. DO AN ACTION === The team must decide to make one of the following actions: ==== A. TRY TO SOLVE A CHALLENGE ==== Every challenge token has three data items: The region where it appears, the MDG affected by it, and the needed resource to solve it. If in the moment to choose an action, the convenient resource is on the same region than a challenge which needs it, the team my try to solve the challenge. A question associated to that MDG will be asked. ''If you answer correctly'', move forward the score marker associated to the MDG indicated by the challeng three boxes towards a higher score. It's not possible to move an score token beyond 100 points. If the score marker shows an X, turn it upside down to see the green tick. In the same manner, turn the region marker, where the challenge is located, upside down, if it wasn't showing the green tick yet. Likewise, if the resource was 'locked', turn it upside down, in order to unlock its power. The challenge token is discarded and place it in the discarded pile, marked with an X on the board. ''If you answer incorrectly'', don't move any marker or token. ''In both cases'', leave the question card on the discard pile, marked with an X, next to que question mark on the board. Place it with the questions facing up. ==== B. MOVE A RESOURCE TO AN ADJACENT REGION ==== All regions are linked between them, indicated by the black arrows on the board. You can move one resource from one region to another linked region, as an action. If by moving a resource to a region, in this region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ==== C. USE AN UNLOCKED RESOURCE POWER ==== If a resource has its power unlocked, you can use its power and turn that resource upside down (then you lock its power again). All powers are the following: ===== Economic resources ===== Swap places of two resources on the board. Economic resources may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Professionals ===== Move a resource to any region on the board. Professionals may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Materials ===== . Move towards higher score one box the score token of one of the following MDGS: 1, 2, 6, 7. ===== Politics ===== Move towards higher score one box the score token of one of the following MDGS: 3, 4, 5, 8. ===== Justice ===== You can discard a challenge token placed in any region, but it's not treated as solved. ===== Education ===== This is the only power that cant't be used in '1. Do an action' phase, but you can use it immediatly after you answer incorrectly a question. You can ask a second question to try to solve that challenge. === 2. A NEW CHALLENGE APPEARS === The challenge we left in the space marked by an eye on the board, is the next challenge that will appear in the game. Grab that challenge and place it on the region indicated by the leaf shape. In that moment, if in that region there was any other unsolved challenges, move one box towards a lower score, on the score board, all MDGs markers present in this region's challenges, without counting on th new challenge. ==== '-1' TOKEN ==== If the next challenge token is a'-1' one, check all unsolved challenges on the board and move one box towards a lower score, on the score board, all MDGs markeres present. Only one box may be moved per MDG, so ignore other challenges that references the same MDG. In that moment, grab all tokens from discarded challenges pile (marked with an X on the board) and the '-1' token and put them back into the bag. Grab a new challenge token from the bag, randomly, and place it on the space marked with an eye. Now you know which is the challenge for the next round. == END OF THE GAME == There are two possible scenarios when the game ends: 1. ''The team loses the game'', if in any moment of the game, any MDG score marker reaches the skull. If you want to calculate your final score, see the "Scoring. If we lose." section below. 2. ''The team wins the game'', if in any moment of the game, all MDG score markers show the green tick and all region markers show the green tick as well. If this situation occurs in the middle of several challenges solving, you can end solving up all of them (and also use the Education power, if this is unlocked). == SCORING == === If we lose === If our team has lost the game, move towards a lower score, all MDG markers, 3 boxes. If any of the markers reaches the skull, it cannot be moved beyond. Then, sum up all the scores, knowing the skull scores 0 points. === If we won === Sum up all scores of all MDGs markers and this will be your final score. (On the score board you can see an aid for suming up to three markers on the same score box, on grey). 89fc073b4d7ae7a4d60a268ff2f809643dcbd694 1249 1248 2014-10-17T16:46:53Z Lennon 5509 /* THE GAME */ wikitext text/x-wiki == このゲームの目的 == ボードゲーム・INJAWARAの目的はチームで協力し、各MDGに関連する少なくともひとつの課題を解決するために貢献をすることです。 そして、各6領域にひとつづつのリソースを移動させることにより、直面した課題に関連する問題に答えることです。 長い間問題を放置しておくことはよくありません。多くはより悪い方向に向かいます! 問題があまりにも深刻になりすぎた場合、あなたが問題を解決することは不可能となります。 そしてあなたは何もかも失うことになります... == ゲーム == ボードゲーム・INJAWARAに、プレイヤーのターンというものはありません。 しかし、各ラウンドごとに、すべてのプレイヤーは、チームとして、実行するアクションを決定する必要があります。 どのような行動をするか決めるためには、すべてのプレイヤーが同意しなければなりません。 各ラウンドには、2つの段階があります。 === 1.アクションを実行する === チームでいずれか一つの操作をすることを決定しなければなりません: ==== A.課題の解決に挑む ==== すべての課題トークンには、3つのデータの項目があります: ・課題トークの置かれる領域 ・課題トークンの解決によって影響の受けるMDG ・課題を解決するにあたり、必要なリソース アクションを選択した瞬間に、リソースがそれを必要とする課題と領域にあった場合は、 チームと自分の力で課題を解決しよう。 問題は、課題トークンのMDGに関連した質問をします。 ''If you answer correctly'', move forward the score marker associated to the MDG indicated by the challeng three boxes towards a higher score. It's not possible to move an score token beyond 100 points. If the score marker shows an X, turn it upside down to see the green tick. In the same manner, turn the region marker, where the challenge is located, upside down, if it wasn't showing the green tick yet. Likewise, if the resource was 'locked', turn it upside down, in order to unlock its power. The challenge token is discarded and place it in the discarded pile, marked with an X on the board. ''If you answer incorrectly'', don't move any marker or token. ''In both cases'', leave the question card on the discard pile, marked with an X, next to que question mark on the board. Place it with the questions facing up. ==== B. MOVE A RESOURCE TO AN ADJACENT REGION ==== All regions are linked between them, indicated by the black arrows on the board. You can move one resource from one region to another linked region, as an action. If by moving a resource to a region, in this region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ==== C. USE AN UNLOCKED RESOURCE POWER ==== If a resource has its power unlocked, you can use its power and turn that resource upside down (then you lock its power again). All powers are the following: ===== Economic resources ===== Swap places of two resources on the board. Economic resources may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Professionals ===== Move a resource to any region on the board. Professionals may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Materials ===== . Move towards higher score one box the score token of one of the following MDGS: 1, 2, 6, 7. ===== Politics ===== Move towards higher score one box the score token of one of the following MDGS: 3, 4, 5, 8. ===== Justice ===== You can discard a challenge token placed in any region, but it's not treated as solved. ===== Education ===== This is the only power that cant't be used in '1. Do an action' phase, but you can use it immediatly after you answer incorrectly a question. You can ask a second question to try to solve that challenge. === 2. A NEW CHALLENGE APPEARS === The challenge we left in the space marked by an eye on the board, is the next challenge that will appear in the game. Grab that challenge and place it on the region indicated by the leaf shape. In that moment, if in that region there was any other unsolved challenges, move one box towards a lower score, on the score board, all MDGs markers present in this region's challenges, without counting on th new challenge. ==== '-1' TOKEN ==== If the next challenge token is a'-1' one, check all unsolved challenges on the board and move one box towards a lower score, on the score board, all MDGs markeres present. Only one box may be moved per MDG, so ignore other challenges that references the same MDG. In that moment, grab all tokens from discarded challenges pile (marked with an X on the board) and the '-1' token and put them back into the bag. Grab a new challenge token from the bag, randomly, and place it on the space marked with an eye. Now you know which is the challenge for the next round. == END OF THE GAME == There are two possible scenarios when the game ends: 1. ''The team loses the game'', if in any moment of the game, any MDG score marker reaches the skull. If you want to calculate your final score, see the "Scoring. If we lose." section below. 2. ''The team wins the game'', if in any moment of the game, all MDG score markers show the green tick and all region markers show the green tick as well. If this situation occurs in the middle of several challenges solving, you can end solving up all of them (and also use the Education power, if this is unlocked). == SCORING == === If we lose === If our team has lost the game, move towards a lower score, all MDG markers, 3 boxes. If any of the markers reaches the skull, it cannot be moved beyond. Then, sum up all the scores, knowing the skull scores 0 points. === If we won === Sum up all scores of all MDGs markers and this will be your final score. (On the score board you can see an aid for suming up to three markers on the same score box, on grey). d078fd2b2b14a08a73f9182d8eaa8ffd91efb09b 1250 1249 2014-10-17T16:48:36Z Lennon 5509 /* このゲームの目的 */ wikitext text/x-wiki == このゲームの目的 == ボードゲーム・INJAWARAの目的はチームで協力し、各MDGに関連する少なくともひとつの課題を解決するために貢献をすることです。 そして、各6領域にひとつづつのリソースを移動させることにより、直面した課題に関連する問題に答えることです。 長い間問題を放置しておくことはよくありません。多くはより悪い方向に向かいます! 問題があまりにも深刻になりすぎた場合、あなたが問題を解決することは不可能となります。 そして、何もかも失うことになります... == ゲーム == ボードゲーム・INJAWARAに、プレイヤーのターンというものはありません。 しかし、各ラウンドごとに、すべてのプレイヤーは、チームとして、実行するアクションを決定する必要があります。 どのような行動をするか決めるためには、すべてのプレイヤーが同意しなければなりません。 各ラウンドには、2つの段階があります。 === 1.アクションを実行する === チームでいずれか一つの操作をすることを決定しなければなりません: ==== A.課題の解決に挑む ==== すべての課題トークンには、3つのデータの項目があります: ・課題トークの置かれる領域 ・課題トークンの解決によって影響の受けるMDG ・課題を解決するにあたり、必要なリソース アクションを選択した瞬間に、リソースがそれを必要とする課題と領域にあった場合は、 チームと自分の力で課題を解決しよう。 問題は、課題トークンのMDGに関連した質問をします。 ''If you answer correctly'', move forward the score marker associated to the MDG indicated by the challeng three boxes towards a higher score. It's not possible to move an score token beyond 100 points. If the score marker shows an X, turn it upside down to see the green tick. In the same manner, turn the region marker, where the challenge is located, upside down, if it wasn't showing the green tick yet. Likewise, if the resource was 'locked', turn it upside down, in order to unlock its power. The challenge token is discarded and place it in the discarded pile, marked with an X on the board. ''If you answer incorrectly'', don't move any marker or token. ''In both cases'', leave the question card on the discard pile, marked with an X, next to que question mark on the board. Place it with the questions facing up. ==== B. MOVE A RESOURCE TO AN ADJACENT REGION ==== All regions are linked between them, indicated by the black arrows on the board. You can move one resource from one region to another linked region, as an action. If by moving a resource to a region, in this region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ==== C. USE AN UNLOCKED RESOURCE POWER ==== If a resource has its power unlocked, you can use its power and turn that resource upside down (then you lock its power again). All powers are the following: ===== Economic resources ===== Swap places of two resources on the board. Economic resources may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Professionals ===== Move a resource to any region on the board. Professionals may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Materials ===== . Move towards higher score one box the score token of one of the following MDGS: 1, 2, 6, 7. ===== Politics ===== Move towards higher score one box the score token of one of the following MDGS: 3, 4, 5, 8. ===== Justice ===== You can discard a challenge token placed in any region, but it's not treated as solved. ===== Education ===== This is the only power that cant't be used in '1. Do an action' phase, but you can use it immediatly after you answer incorrectly a question. You can ask a second question to try to solve that challenge. === 2. A NEW CHALLENGE APPEARS === The challenge we left in the space marked by an eye on the board, is the next challenge that will appear in the game. Grab that challenge and place it on the region indicated by the leaf shape. In that moment, if in that region there was any other unsolved challenges, move one box towards a lower score, on the score board, all MDGs markers present in this region's challenges, without counting on th new challenge. ==== '-1' TOKEN ==== If the next challenge token is a'-1' one, check all unsolved challenges on the board and move one box towards a lower score, on the score board, all MDGs markeres present. Only one box may be moved per MDG, so ignore other challenges that references the same MDG. In that moment, grab all tokens from discarded challenges pile (marked with an X on the board) and the '-1' token and put them back into the bag. Grab a new challenge token from the bag, randomly, and place it on the space marked with an eye. Now you know which is the challenge for the next round. == END OF THE GAME == There are two possible scenarios when the game ends: 1. ''The team loses the game'', if in any moment of the game, any MDG score marker reaches the skull. If you want to calculate your final score, see the "Scoring. If we lose." section below. 2. ''The team wins the game'', if in any moment of the game, all MDG score markers show the green tick and all region markers show the green tick as well. If this situation occurs in the middle of several challenges solving, you can end solving up all of them (and also use the Education power, if this is unlocked). == SCORING == === If we lose === If our team has lost the game, move towards a lower score, all MDG markers, 3 boxes. If any of the markers reaches the skull, it cannot be moved beyond. Then, sum up all the scores, knowing the skull scores 0 points. === If we won === Sum up all scores of all MDGs markers and this will be your final score. (On the score board you can see an aid for suming up to three markers on the same score box, on grey). 5d0dc5e7eab24fe4f50f1a6d7f5ab1e5114defb9 1251 1250 2014-10-17T16:49:00Z Lennon 5509 /* A.課題の解決に挑む */ wikitext text/x-wiki == このゲームの目的 == ボードゲーム・INJAWARAの目的はチームで協力し、各MDGに関連する少なくともひとつの課題を解決するために貢献をすることです。 そして、各6領域にひとつづつのリソースを移動させることにより、直面した課題に関連する問題に答えることです。 長い間問題を放置しておくことはよくありません。多くはより悪い方向に向かいます! 問題があまりにも深刻になりすぎた場合、あなたが問題を解決することは不可能となります。 そして、何もかも失うことになります... == ゲーム == ボードゲーム・INJAWARAに、プレイヤーのターンというものはありません。 しかし、各ラウンドごとに、すべてのプレイヤーは、チームとして、実行するアクションを決定する必要があります。 どのような行動をするか決めるためには、すべてのプレイヤーが同意しなければなりません。 各ラウンドには、2つの段階があります。 === 1.アクションを実行する === チームでいずれか一つの操作をすることを決定しなければなりません: ==== A.課題の解決に挑む ==== すべての課題トークンには、3つのデータの項目があります: ・課題トークンの置かれる領域 ・課題トークンの解決によって影響の受けるMDG ・課題を解決するにあたり、必要なリソース アクションを選択した瞬間に、リソースがそれを必要とする課題と領域にあった場合は、 チームと自分の力で課題を解決しよう。 問題は、課題トークンのMDGに関連した質問をします。 ''If you answer correctly'', move forward the score marker associated to the MDG indicated by the challeng three boxes towards a higher score. It's not possible to move an score token beyond 100 points. If the score marker shows an X, turn it upside down to see the green tick. In the same manner, turn the region marker, where the challenge is located, upside down, if it wasn't showing the green tick yet. Likewise, if the resource was 'locked', turn it upside down, in order to unlock its power. The challenge token is discarded and place it in the discarded pile, marked with an X on the board. ''If you answer incorrectly'', don't move any marker or token. ''In both cases'', leave the question card on the discard pile, marked with an X, next to que question mark on the board. Place it with the questions facing up. ==== B. MOVE A RESOURCE TO AN ADJACENT REGION ==== All regions are linked between them, indicated by the black arrows on the board. You can move one resource from one region to another linked region, as an action. If by moving a resource to a region, in this region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ==== C. USE AN UNLOCKED RESOURCE POWER ==== If a resource has its power unlocked, you can use its power and turn that resource upside down (then you lock its power again). All powers are the following: ===== Economic resources ===== Swap places of two resources on the board. Economic resources may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Professionals ===== Move a resource to any region on the board. Professionals may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Materials ===== . Move towards higher score one box the score token of one of the following MDGS: 1, 2, 6, 7. ===== Politics ===== Move towards higher score one box the score token of one of the following MDGS: 3, 4, 5, 8. ===== Justice ===== You can discard a challenge token placed in any region, but it's not treated as solved. ===== Education ===== This is the only power that cant't be used in '1. Do an action' phase, but you can use it immediatly after you answer incorrectly a question. You can ask a second question to try to solve that challenge. === 2. A NEW CHALLENGE APPEARS === The challenge we left in the space marked by an eye on the board, is the next challenge that will appear in the game. Grab that challenge and place it on the region indicated by the leaf shape. In that moment, if in that region there was any other unsolved challenges, move one box towards a lower score, on the score board, all MDGs markers present in this region's challenges, without counting on th new challenge. ==== '-1' TOKEN ==== If the next challenge token is a'-1' one, check all unsolved challenges on the board and move one box towards a lower score, on the score board, all MDGs markeres present. Only one box may be moved per MDG, so ignore other challenges that references the same MDG. In that moment, grab all tokens from discarded challenges pile (marked with an X on the board) and the '-1' token and put them back into the bag. Grab a new challenge token from the bag, randomly, and place it on the space marked with an eye. Now you know which is the challenge for the next round. == END OF THE GAME == There are two possible scenarios when the game ends: 1. ''The team loses the game'', if in any moment of the game, any MDG score marker reaches the skull. If you want to calculate your final score, see the "Scoring. If we lose." section below. 2. ''The team wins the game'', if in any moment of the game, all MDG score markers show the green tick and all region markers show the green tick as well. If this situation occurs in the middle of several challenges solving, you can end solving up all of them (and also use the Education power, if this is unlocked). == SCORING == === If we lose === If our team has lost the game, move towards a lower score, all MDG markers, 3 boxes. If any of the markers reaches the skull, it cannot be moved beyond. Then, sum up all the scores, knowing the skull scores 0 points. === If we won === Sum up all scores of all MDGs markers and this will be your final score. (On the score board you can see an aid for suming up to three markers on the same score box, on grey). 50857a8b4ee02ba289fbd9603a59cc22b3ccc98a Gamehelpinjawara 0 173 1252 1251 2014-10-17T16:49:49Z Lennon 5509 /* A.課題の解決に挑む */ wikitext text/x-wiki == このゲームの目的 == ボードゲーム・INJAWARAの目的はチームで協力し、各MDGに関連する少なくともひとつの課題を解決するために貢献をすることです。 そして、各6領域にひとつづつのリソースを移動させることにより、直面した課題に関連する問題に答えることです。 長い間問題を放置しておくことはよくありません。多くはより悪い方向に向かいます! 問題があまりにも深刻になりすぎた場合、あなたが問題を解決することは不可能となります。 そして、何もかも失うことになります... == ゲーム == ボードゲーム・INJAWARAに、プレイヤーのターンというものはありません。 しかし、各ラウンドごとに、すべてのプレイヤーは、チームとして、実行するアクションを決定する必要があります。 どのような行動をするか決めるためには、すべてのプレイヤーが同意しなければなりません。 各ラウンドには、2つの段階があります。 === 1.アクションを実行する === チームでいずれか一つの操作をすることを決定しなければなりません: ==== A.課題の解決に挑む ==== すべての課題トークンには、3つのデータの項目があります: ・課題トークンの置かれる領域 ・課題トークンの解決によって影響の受けるMDG ・課題を解決するにあたり、必要なリソース アクションを選択した瞬間に、リソースがそれを必要とする課題と領域にあった場合、 チームと自分は課題を解決することを試みます。 問題は、課題トークンのMDGに関連した質問をします。 ''If you answer correctly'', move forward the score marker associated to the MDG indicated by the challeng three boxes towards a higher score. It's not possible to move an score token beyond 100 points. If the score marker shows an X, turn it upside down to see the green tick. In the same manner, turn the region marker, where the challenge is located, upside down, if it wasn't showing the green tick yet. Likewise, if the resource was 'locked', turn it upside down, in order to unlock its power. The challenge token is discarded and place it in the discarded pile, marked with an X on the board. ''If you answer incorrectly'', don't move any marker or token. ''In both cases'', leave the question card on the discard pile, marked with an X, next to que question mark on the board. Place it with the questions facing up. ==== B. MOVE A RESOURCE TO AN ADJACENT REGION ==== All regions are linked between them, indicated by the black arrows on the board. You can move one resource from one region to another linked region, as an action. If by moving a resource to a region, in this region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ==== C. USE AN UNLOCKED RESOURCE POWER ==== If a resource has its power unlocked, you can use its power and turn that resource upside down (then you lock its power again). All powers are the following: ===== Economic resources ===== Swap places of two resources on the board. Economic resources may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Professionals ===== Move a resource to any region on the board. Professionals may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Materials ===== . Move towards higher score one box the score token of one of the following MDGS: 1, 2, 6, 7. ===== Politics ===== Move towards higher score one box the score token of one of the following MDGS: 3, 4, 5, 8. ===== Justice ===== You can discard a challenge token placed in any region, but it's not treated as solved. ===== Education ===== This is the only power that cant't be used in '1. Do an action' phase, but you can use it immediatly after you answer incorrectly a question. You can ask a second question to try to solve that challenge. === 2. A NEW CHALLENGE APPEARS === The challenge we left in the space marked by an eye on the board, is the next challenge that will appear in the game. Grab that challenge and place it on the region indicated by the leaf shape. In that moment, if in that region there was any other unsolved challenges, move one box towards a lower score, on the score board, all MDGs markers present in this region's challenges, without counting on th new challenge. ==== '-1' TOKEN ==== If the next challenge token is a'-1' one, check all unsolved challenges on the board and move one box towards a lower score, on the score board, all MDGs markeres present. Only one box may be moved per MDG, so ignore other challenges that references the same MDG. In that moment, grab all tokens from discarded challenges pile (marked with an X on the board) and the '-1' token and put them back into the bag. Grab a new challenge token from the bag, randomly, and place it on the space marked with an eye. Now you know which is the challenge for the next round. == END OF THE GAME == There are two possible scenarios when the game ends: 1. ''The team loses the game'', if in any moment of the game, any MDG score marker reaches the skull. If you want to calculate your final score, see the "Scoring. If we lose." section below. 2. ''The team wins the game'', if in any moment of the game, all MDG score markers show the green tick and all region markers show the green tick as well. If this situation occurs in the middle of several challenges solving, you can end solving up all of them (and also use the Education power, if this is unlocked). == SCORING == === If we lose === If our team has lost the game, move towards a lower score, all MDG markers, 3 boxes. If any of the markers reaches the skull, it cannot be moved beyond. Then, sum up all the scores, knowing the skull scores 0 points. === If we won === Sum up all scores of all MDGs markers and this will be your final score. (On the score board you can see an aid for suming up to three markers on the same score box, on grey). 830833fa104405cddd45c3355b8928e6860fe76f 1253 1252 2014-10-17T19:59:28Z Vonhell 194 Undo revision 1252 by [[Special:Contributions/Lennon|Lennon]] ([[User talk:Lennon|talk]]) wikitext text/x-wiki == このゲームの目的 == ボードゲーム・INJAWARAの目的はチームで協力し、各MDGに関連する少なくともひとつの課題を解決するために貢献をすることです。 そして、各6領域にひとつづつのリソースを移動させることにより、直面した課題に関連する問題に答えることです。 長い間問題を放置しておくことはよくありません。多くはより悪い方向に向かいます! 問題があまりにも深刻になりすぎた場合、あなたが問題を解決することは不可能となります。 そして、何もかも失うことになります... == ゲーム == ボードゲーム・INJAWARAに、プレイヤーのターンというものはありません。 しかし、各ラウンドごとに、すべてのプレイヤーは、チームとして、実行するアクションを決定する必要があります。 どのような行動をするか決めるためには、すべてのプレイヤーが同意しなければなりません。 各ラウンドには、2つの段階があります。 === 1.アクションを実行する === チームでいずれか一つの操作をすることを決定しなければなりません: ==== A.課題の解決に挑む ==== すべての課題トークンには、3つのデータの項目があります: ・課題トークンの置かれる領域 ・課題トークンの解決によって影響の受けるMDG ・課題を解決するにあたり、必要なリソース アクションを選択した瞬間に、リソースがそれを必要とする課題と領域にあった場合は、 チームと自分の力で課題を解決しよう。 問題は、課題トークンのMDGに関連した質問をします。 ''If you answer correctly'', move forward the score marker associated to the MDG indicated by the challeng three boxes towards a higher score. It's not possible to move an score token beyond 100 points. If the score marker shows an X, turn it upside down to see the green tick. In the same manner, turn the region marker, where the challenge is located, upside down, if it wasn't showing the green tick yet. Likewise, if the resource was 'locked', turn it upside down, in order to unlock its power. The challenge token is discarded and place it in the discarded pile, marked with an X on the board. ''If you answer incorrectly'', don't move any marker or token. ''In both cases'', leave the question card on the discard pile, marked with an X, next to que question mark on the board. Place it with the questions facing up. ==== B. MOVE A RESOURCE TO AN ADJACENT REGION ==== All regions are linked between them, indicated by the black arrows on the board. You can move one resource from one region to another linked region, as an action. If by moving a resource to a region, in this region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ==== C. USE AN UNLOCKED RESOURCE POWER ==== If a resource has its power unlocked, you can use its power and turn that resource upside down (then you lock its power again). All powers are the following: ===== Economic resources ===== Swap places of two resources on the board. Economic resources may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Professionals ===== Move a resource to any region on the board. Professionals may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Materials ===== . Move towards higher score one box the score token of one of the following MDGS: 1, 2, 6, 7. ===== Politics ===== Move towards higher score one box the score token of one of the following MDGS: 3, 4, 5, 8. ===== Justice ===== You can discard a challenge token placed in any region, but it's not treated as solved. ===== Education ===== This is the only power that cant't be used in '1. Do an action' phase, but you can use it immediatly after you answer incorrectly a question. You can ask a second question to try to solve that challenge. === 2. A NEW CHALLENGE APPEARS === The challenge we left in the space marked by an eye on the board, is the next challenge that will appear in the game. Grab that challenge and place it on the region indicated by the leaf shape. In that moment, if in that region there was any other unsolved challenges, move one box towards a lower score, on the score board, all MDGs markers present in this region's challenges, without counting on th new challenge. ==== '-1' TOKEN ==== If the next challenge token is a'-1' one, check all unsolved challenges on the board and move one box towards a lower score, on the score board, all MDGs markeres present. Only one box may be moved per MDG, so ignore other challenges that references the same MDG. In that moment, grab all tokens from discarded challenges pile (marked with an X on the board) and the '-1' token and put them back into the bag. Grab a new challenge token from the bag, randomly, and place it on the space marked with an eye. Now you know which is the challenge for the next round. == END OF THE GAME == There are two possible scenarios when the game ends: 1. ''The team loses the game'', if in any moment of the game, any MDG score marker reaches the skull. If you want to calculate your final score, see the "Scoring. If we lose." section below. 2. ''The team wins the game'', if in any moment of the game, all MDG score markers show the green tick and all region markers show the green tick as well. If this situation occurs in the middle of several challenges solving, you can end solving up all of them (and also use the Education power, if this is unlocked). == SCORING == === If we lose === If our team has lost the game, move towards a lower score, all MDG markers, 3 boxes. If any of the markers reaches the skull, it cannot be moved beyond. Then, sum up all the scores, knowing the skull scores 0 points. === If we won === Sum up all scores of all MDGs markers and this will be your final score. (On the score board you can see an aid for suming up to three markers on the same score box, on grey). 50857a8b4ee02ba289fbd9603a59cc22b3ccc98a 1254 1253 2014-10-17T20:00:26Z Vonhell 194 Undo revision 1251 by [[Special:Contributions/Lennon|Lennon]] ([[User talk:Lennon|talk]]) wikitext text/x-wiki == このゲームの目的 == ボードゲーム・INJAWARAの目的はチームで協力し、各MDGに関連する少なくともひとつの課題を解決するために貢献をすることです。 そして、各6領域にひとつづつのリソースを移動させることにより、直面した課題に関連する問題に答えることです。 長い間問題を放置しておくことはよくありません。多くはより悪い方向に向かいます! 問題があまりにも深刻になりすぎた場合、あなたが問題を解決することは不可能となります。 そして、何もかも失うことになります... == ゲーム == ボードゲーム・INJAWARAに、プレイヤーのターンというものはありません。 しかし、各ラウンドごとに、すべてのプレイヤーは、チームとして、実行するアクションを決定する必要があります。 どのような行動をするか決めるためには、すべてのプレイヤーが同意しなければなりません。 各ラウンドには、2つの段階があります。 === 1.アクションを実行する === チームでいずれか一つの操作をすることを決定しなければなりません: ==== A.課題の解決に挑む ==== すべての課題トークンには、3つのデータの項目があります: ・課題トークの置かれる領域 ・課題トークンの解決によって影響の受けるMDG ・課題を解決するにあたり、必要なリソース アクションを選択した瞬間に、リソースがそれを必要とする課題と領域にあった場合は、 チームと自分の力で課題を解決しよう。 問題は、課題トークンのMDGに関連した質問をします。 ''If you answer correctly'', move forward the score marker associated to the MDG indicated by the challeng three boxes towards a higher score. It's not possible to move an score token beyond 100 points. If the score marker shows an X, turn it upside down to see the green tick. In the same manner, turn the region marker, where the challenge is located, upside down, if it wasn't showing the green tick yet. Likewise, if the resource was 'locked', turn it upside down, in order to unlock its power. The challenge token is discarded and place it in the discarded pile, marked with an X on the board. ''If you answer incorrectly'', don't move any marker or token. ''In both cases'', leave the question card on the discard pile, marked with an X, next to que question mark on the board. Place it with the questions facing up. ==== B. MOVE A RESOURCE TO AN ADJACENT REGION ==== All regions are linked between them, indicated by the black arrows on the board. You can move one resource from one region to another linked region, as an action. If by moving a resource to a region, in this region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ==== C. USE AN UNLOCKED RESOURCE POWER ==== If a resource has its power unlocked, you can use its power and turn that resource upside down (then you lock its power again). All powers are the following: ===== Economic resources ===== Swap places of two resources on the board. Economic resources may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Professionals ===== Move a resource to any region on the board. Professionals may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Materials ===== . Move towards higher score one box the score token of one of the following MDGS: 1, 2, 6, 7. ===== Politics ===== Move towards higher score one box the score token of one of the following MDGS: 3, 4, 5, 8. ===== Justice ===== You can discard a challenge token placed in any region, but it's not treated as solved. ===== Education ===== This is the only power that cant't be used in '1. Do an action' phase, but you can use it immediatly after you answer incorrectly a question. You can ask a second question to try to solve that challenge. === 2. A NEW CHALLENGE APPEARS === The challenge we left in the space marked by an eye on the board, is the next challenge that will appear in the game. Grab that challenge and place it on the region indicated by the leaf shape. In that moment, if in that region there was any other unsolved challenges, move one box towards a lower score, on the score board, all MDGs markers present in this region's challenges, without counting on th new challenge. ==== '-1' TOKEN ==== If the next challenge token is a'-1' one, check all unsolved challenges on the board and move one box towards a lower score, on the score board, all MDGs markeres present. Only one box may be moved per MDG, so ignore other challenges that references the same MDG. In that moment, grab all tokens from discarded challenges pile (marked with an X on the board) and the '-1' token and put them back into the bag. Grab a new challenge token from the bag, randomly, and place it on the space marked with an eye. Now you know which is the challenge for the next round. == END OF THE GAME == There are two possible scenarios when the game ends: 1. ''The team loses the game'', if in any moment of the game, any MDG score marker reaches the skull. If you want to calculate your final score, see the "Scoring. If we lose." section below. 2. ''The team wins the game'', if in any moment of the game, all MDG score markers show the green tick and all region markers show the green tick as well. If this situation occurs in the middle of several challenges solving, you can end solving up all of them (and also use the Education power, if this is unlocked). == SCORING == === If we lose === If our team has lost the game, move towards a lower score, all MDG markers, 3 boxes. If any of the markers reaches the skull, it cannot be moved beyond. Then, sum up all the scores, knowing the skull scores 0 points. === If we won === Sum up all scores of all MDGs markers and this will be your final score. (On the score board you can see an aid for suming up to three markers on the same score box, on grey). 5d0dc5e7eab24fe4f50f1a6d7f5ab1e5114defb9 1255 1254 2014-10-17T20:04:24Z Vonhell 194 wikitext text/x-wiki == AIM OF THE GAME == The aim of the INJAWARA board game is to work in team cooperatively and contribute to solve at least 1 Challenge related to each Millennium Development Goal and 1 for each Region by moving the needed resources through the six regions and reply to questions related to the Challenges faced. The longer you ignore a problem, the more it will get worse! If a problem becomes too serious it will become impossible to solve it, and you will lose all. == THE GAME == The INJAWARA board game has no player turns, but in each round, all players, as a team, must decide the action to do. How decisions are taken must be agreed by all players at the beginning of the game. Every round has two phases: === 1. DO AN ACTION === The team must decide to make one of the following actions: ==== A. TRY TO SOLVE A CHALLENGE ==== Every challenge token has three data items: The region where it appears, the MDG affected by it, and the needed resource to solve it. If in the moment to choose an action, the convenient resource is on the same region than a challenge which needs it, the team my try to solve the challenge. A question associated to that MDG will be asked. ''If you answer correctly'', move forward the score marker associated to the MDG indicated by the challeng three boxes towards a higher score. It's not possible to move an score token beyond 100 points. If the score marker shows an X, turn it upside down to see the green tick. In the same manner, turn the region marker, where the challenge is located, upside down, if it wasn't showing the green tick yet. Likewise, if the resource was 'locked', turn it upside down, in order to unlock its power. The challenge token is discarded and place it in the discarded pile, marked with an X on the board. ''If you answer incorrectly'', don't move any marker or token. ''In both cases'', leave the question card on the discard pile, marked with an X, next to que question mark on the board. Place it with the questions facing up. ==== B. MOVE A RESOURCE TO AN ADJACENT REGION ==== All regions are linked between them, indicated by the black arrows on the board. You can move one resource from one region to another linked region, as an action. If by moving a resource to a region, in this region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ==== C. USE AN UNLOCKED RESOURCE POWER ==== If a resource has its power unlocked, you can use its power and turn that resource upside down (then you lock its power again). All powers are the following: ===== Economic resources ===== Swap places of two resources on the board. Economic resources may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Professionals ===== Move a resource to any region on the board. Professionals may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Materials ===== . Move towards higher score one box the score token of one of the following MDGS: 1, 2, 6, 7. ===== Politics ===== Move towards higher score one box the score token of one of the following MDGS: 3, 4, 5, 8. ===== Justice ===== You can discard a challenge token placed in any region, but it's not treated as solved. ===== Education ===== This is the only power that cant't be used in '1. Do an action' phase, but you can use it immediatly after you answer incorrectly a question. You can ask a second question to try to solve that challenge. === 2. A NEW CHALLENGE APPEARS === The challenge we left in the space marked by an eye on the board, is the next challenge that will appear in the game. Grab that challenge and place it on the region indicated by the leaf shape. In that moment, if in that region there was any other unsolved challenges, move one box towards a lower score, on the score board, all MDGs markers present in this region's challenges, without counting on th new challenge. ==== '-1' TOKEN ==== If the next challenge token is a'-1' one, check all unsolved challenges on the board and move one box towards a lower score, on the score board, all MDGs markeres present. Only one box may be moved per MDG, so ignore other challenges that references the same MDG. In that moment, grab all tokens from discarded challenges pile (marked with an X on the board) and the '-1' token and put them back into the bag. Grab a new challenge token from the bag, randomly, and place it on the space marked with an eye. Now you know which is the challenge for the next round. == END OF THE GAME == There are two possible scenarios when the game ends: 1. ''The team loses the game'', if in any moment of the game, any MDG score marker reaches the skull. If you want to calculate your final score, see the "Scoring. If we lose." section below. 2. ''The team wins the game'', if in any moment of the game, all MDG score markers show the green tick and all region markers show the green tick as well. If this situation occurs in the middle of several challenges solving, you can end solving up all of them (and also use the Education power, if this is unlocked). == SCORING == === If we lose === If our team has lost the game, move towards a lower score, all MDG markers, 3 boxes. If any of the markers reaches the skull, it cannot be moved beyond. Then, sum up all the scores, knowing the skull scores 0 points. === If we won === Sum up all scores of all MDGs markers and this will be your final score. (On the score board you can see an aid for suming up to three markers on the same score box, on grey). 6ae4153e87f51d0d2b4d45538485bed54a206ee3 1256 1255 2014-10-17T23:31:51Z Lennon 5509 /* AIM OF THE GAME */ wikitext text/x-wiki == AIM OF THE GAME == The aim of the INJAWARA board game is to work in team cooperatively and contribute to solve at least 1 Challenge related to each Millennium Development Goal and 1 for each Region by moving the needed resources through the six regions and reply to questions related to the Challenges faced. The longer you ignore a problem, the more it will get worse! If a problem becomes too serious it will become impossible to solve it, and you will lose all. == THE GAME == The INJAWARA board game has no player turns, but in each round, all players, as a team, must decide the action to do. How decisions are taken must be agreed by all players at the beginning of the game. Every round has two phases: === 1. DO AN ACTION === The team must decide to make one of the following actions: ==== A. TRY TO SOLVE A CHALLENGE ==== Every challenge token has three data items: The region where it appears, the MDG affected by it, and the needed resource to solve it. If in the moment to choose an action, the convenient resource is on the same region than a challenge which needs it, the team my try to solve the challenge. A question associated to that MDG will be asked. ''If you answer correctly'', move forward the score marker associated to the MDG indicated by the challeng three boxes towards a higher score. It's not possible to move an score token beyond 100 points. If the score marker shows an X, turn it upside down to see the green tick. In the same manner, turn the region marker, where the challenge is located, upside down, if it wasn't showing the green tick yet. Likewise, if the resource was 'locked', turn it upside down, in order to unlock its power. The challenge token is discarded and place it in the discarded pile, marked with an X on the board. ''If you answer incorrectly'', don't move any marker or token. ''In both cases'', leave the question card on the discard pile, marked with an X, next to que question mark on the board. Place it with the questions facing up. ==== B. MOVE A RESOURCE TO AN ADJACENT REGION ==== All regions are linked between them, indicated by the black arrows on the board. You can move one resource from one region to another linked region, as an action. If by moving a resource to a region, in this region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ==== C. USE AN UNLOCKED RESOURCE POWER ==== If a resource has its power unlocked, you can use its power and turn that resource upside down (then you lock its power again). All powers are the following: ===== Economic resources ===== Swap places of two resources on the board. Economic resources may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Professionals ===== Move a resource to any region on the board. Professionals may be moved in this way as well. If by using this power, in a region there is one or more challenges which need this resource, the team may try to solve all of them immediately, with no action costs. (see 1.A. section from this rulebook). ===== Materials ===== . Move towards higher score one box the score token of one of the following MDGS: 1, 2, 6, 7. ===== Politics ===== Move towards higher score one box the score token of one of the following MDGS: 3, 4, 5, 8. ===== Justice ===== You can discard a challenge token placed in any region, but it's not treated as solved. ===== Education ===== This is the only power that cant't be used in '1. Do an action' phase, but you can use it immediatly after you answer incorrectly a question. You can ask a second question to try to solve that challenge. === 2. A NEW CHALLENGE APPEARS === The challenge we left in the space marked by an eye on the board, is the next challenge that will appear in the game. Grab that challenge and place it on the region indicated by the leaf shape. In that moment, if in that region there was any other unsolved challenges, move one box towards a lower score, on the score board, all MDGs markers present in this region's challenges, without counting on th new challenge. ==== '-1' TOKEN ==== If the next challenge token is a'-1' one, check all unsolved challenges on the board and move one box towards a lower score, on the score board, all MDGs markeres present. Only one box may be moved per MDG, so ignore other challenges that references the same MDG. In that moment, grab all tokens from discarded challenges pile (marked with an X on the board) and the '-1' token and put them back into the bag. Grab a new challenge token from the bag, randomly, and place it on the space marked with an eye. Now you know which is the challenge for the next round. == END OF THE GAME == There are two possible scenarios when the game ends: 1. ''The team loses the game'', if in any moment of the game, any MDG score marker reaches the skull. If you want to calculate your final score, see the "Scoring. If we lose." section below. 2. ''The team wins the game'', if in any moment of the game, all MDG score markers show the green tick and all region markers show the green tick as well. If this situation occurs in the middle of several challenges solving, you can end solving up all of them (and also use the Education power, if this is unlocked). == SCORING == === If we lose === If our team has lost the game, move towards a lower score, all MDG markers, 3 boxes. If any of the markers reaches the skull, it cannot be moved beyond. Then, sum up all the scores, knowing the skull scores 0 points. === If we won === Sum up all scores of all MDGs markers and this will be your final score. (On the score board you can see an aid for suming up to three markers on the same score box, on grey). d81aef9d19c6d21bb80feaa64f79f7fe74c23a29 1275 1256 2014-10-23T11:36:14Z Adela82 4198 New rules update wikitext text/x-wiki == AIM OF THE GAME == The aim of the INJAWARA board game is to work in team cooperatively and contribute to solve at least 1 Challenge related to each Millennium Development Goal and 1 for each Region by moving the needed resources through the six regions and reply to questions related to the Challenges faced. The longer you ignore a problem, the more it will get worse! If a problem becomes too serious it will become impossible to solve it, and you will lose all. == THE GAME == The INJAWARA board game has no player turns, but in each round, all players, as a team, must decide the actions to do. How decisions are taken must be agreed by all players at the beginning of the game. Every round has three phases: === 1. USE OR MOVE RESOURCES (Optional) === Optionally, the team may make one of the following actions: move a resource to an adjacent region, use one unlocked resource power or simply do nothing in this phase. ==== A. MOVE A RESOURCE TO AN ADJACENT REGION ==== All regions are linked between them, indicated by the black arrows on the board. You can move one resource from one region to another linked region. ==== B. USE AN UNLOCKED RESOURCE POWER ==== If a resource has its power unlocked, you can use its power. Please note that after using the power of a resource you have to lock its power again and turn that resource upside down. All powers are the following: ===== Economic resources ===== Swap places of two resources on the board. Economic resources may be moved in this way as well. ===== Professionals ===== Move a resource to any region on the board. Professionals may be moved in this way as well. ===== Materials ===== Move towards higher score one box the score token of one of the following MDGS: 1, 2, 6, 7. ===== Politics ===== Move towards higher score one box the score token of one of the following MDGS: 3, 4, 5, 8. ===== Justice ===== You can discard a challenge token placed in any region, but it's not treated as solved. ===== Education ===== This is the only resource you have to use after having answered to the question. You can answer another questions, after failing a previous one, in order to solve a challenge. ==== C. DO NOTHING ==== Whilst there is a challenge which may be solved (see 2. Try to solve a challenge), we can skip this first phase and go straight for the challenge. In the same manner, althought there was not a challenge which may be solved, it's possible for the team to pass in this phase and go just right to 3. A NEW CHALLENGE APPEARS. This is an actual valid option, but encourage the team to use it carefully. Maybe you can earn some more points by moving a resource or using a power, instead of letting the turn move on. === 2. TRY TO SOLVE A CHALLENGE (if it's possible) === Every challenge token has three data items: The region where it appears, the MDG affected by it, and the needed resource to solve it. If in the moment to start the turn or after using or moving resources, the convenient resource is on the same region than a challenge which needs it, the team my try to solve the challenge (see illustration). There is only one constraint: If you chose to move a resource at the beginning of the turn, you may only try to solve the challenges associated to that resource. This doesn't apply after using a power or if you decide not to move nor use a resource. If there is more than one challenge you can solve, YOU CANNOT SOLVE BOTH, but you have to choose which one you want to solve. So, grab the first question card from the question deck, and read out loud the question related to the MDG indicated by the challenge, and try to answer it working as a team. The right answers are in the reverse of the card, so try not to lift it up as others may see the answer. If you answer correctly, move forward the score marker associated to the MDG indicated by the challenge three boxes towards a higher score. It's not possible to move an score token beyond 100 points. If the score marker shows an X, turn it upside down to see the green tick. In the same manner, turn the region marker, where the challenge is located, upside down, if it wasn't showing the green tick yet. Likewise, if the resource was 'locked', turn it upside down, in order to unlock its power. The challenge token is discarded and place it in the discarded pile, marked with an X on the board. If you answer incorrectly, don't move any marker or token. In both cases, leave the question card on the discard pile, marked with an X, next to que question mark on the board. Place it with the questions facing up. === 3. A NEW CHALLENGE APPEARS === The challenge we left in the space marked by an eye on the board, is the next challenge that will appear in the game. Grab that challenge and place it on the region indicated by the leaf shape. In that moment, if in that region there was any other unsolved challenges, move one box towards a lower score, on the score board, all MDGs markers present in this region's challenges, without counting on th new challenge. ==== '-1' TOKEN ==== If the next challenge token is a'-1' one, check all unsolved challenges on the board and move one box towards a lower score, on the score board, all MDGs markeres present. Only one box may be moved per MDG, so ignore other challenges that references the same MDG. In that moment, grab all tokens from discarded challenges pile (marked with an X on the board) and the '-1' token and put them back into the bag. Grab a new challenge token from the bag, randomly, and place it on the space marked with an eye. Now you know which is the challenge for the next round. == END OF THE GAME == There are two possible scenarios when the game ends: 1. ''The team loses the game'', if in any moment of the game, any MDG score marker reaches the skull. If you want to calculate your final score, see the "Scoring. If we lose." section below. 2. ''The team wins the game'', if in any moment of the game, all MDG score markers show the green tick and all region markers show the green tick as well. If this situation occurs in the middle of several challenges solving, you can end solving up all of them (and also use the Education power, if this is unlocked). == SCORING == === If we lose === If our team has lost the game, move towards a lower score, all MDG markers, 3 boxes. If any of the markers reaches the skull, it cannot be moved beyond. Then, sum up all the scores, knowing the skull scores 0 points. === If we won === Sum up all scores of all MDGs markers and this will be your final score. (On the score board you can see an aid for suming up to three markers on the same score box, on grey). d18a3f62f671c6c445f27e817ba1e47d17f67ed4 Gamehelpcheckers 0 171 1257 1233 2014-10-21T08:48:04Z Pejsek 2143 wikitext text/x-wiki == Objective of the Game == Checkers, also known as 'draughts', is a timeless abstract strategy game for two players dating back almost a thousand years. In the game you move your pieces until you've jumped over all pieces of your opponent and have removed them from the board. Players move one piece diagonally at a time in alternating play (starting with light). All references to squares refer to the dark squares only. The board is an 8 by 8 square of squares in alternating light or dark colours. Players should set up pieces on the 12 dark squares in the first three rows closest to them (the light spaces are completely ignored in the game), setting up three rows of 4 checkers. ==Moving & Capturing in straight checkers== Take turns moving a checker one space diagonally forward towards the opponent's side of the board on a square that contains no checkers of either player. You may 'jump' your opponents checkers by making a capturing move if your checker is located at most one space behind your opponent's checker (on your side). When capturing you jump over the checker moving two spaces in the same direction and then remove their piece from the game. Capturing multiple pieces using multiple jumps in the same turn is a key part of the game, when doing so you may change which direction they're moving diagonally, but they must still always move forward. :* If you have the opportunity to jump your opponent's checker, you must. :* You may continue capturing subsequent checkers until there are no more possible captures. :* If you have the opportunity to jump a choice of opponent's checkers, you may choose which but must capture one of them. ==Kings in straight checkers== When one of your pieces reaches the end of the opponent's board that piece is upgraded to a king, these may move in either direction now. :* Kings may move forward or backward diagonally. :* Kings can still only move one diagonal space at a time unless capturing. :* Kings may move both forward and backward in the same turn when capturing. ==Winning== Complete ''one'' of the following three objectives; :* Capture all of an opponent's pieces. '''or''' :* Block all your opponent's pieces so they can't make any more moves. '''or''' :* Have all your pieces on the opponent's far end of the board (your opponent will need to have captured half or more of your pieces). ==Draws== A draw is declared if ''any'' of these conditions occur; :* A game is a draw if neither opponent has the possibility to win the game. '''or''' :* The game is considered a draw when the same situation repeats itself for the third time (not necessarily consecutive). '''or''' :* A one king against one king endgame is often declared a draw. ==Strategy== :* Be aggressive, you are more likely to win. Playing to the board sides are safer though without reward. :* Forward- always forward, it's alright to lose pieces as long as you take the opponent's, save your kings. :* Safety in numbers, don't leave your pieces alone, move them one after another in small groups to protect them. :* Protect the rear, protect forward or don't move your end row pieces as long as possible to prevent opponent's kings. :* Sacrifice when needed. draw out your opponent so you can get 2-1 trades the following turn, don't expose your kings without reward. :* Each king you get is a huge bonus, try to get as many as possible and don't waste them, sacrificing several pieces for a king can be alright. :* Don't forget to block your opponent when possible, you make not only that piece vulnerable but fail to protect it with a counter and give your opponent the chance to take multiple of your pieces in one turn. e992857d282cbe64ac9eab7f62326b5eefdebacc 1258 1257 2014-10-21T08:48:30Z Pejsek 2143 wikitext text/x-wiki == Objective of the Game == Checkers, also known as 'draughts', is a timeless abstract strategy game for two players dating back almost a thousand years. In the game you move your pieces until you've jumped over all pieces of your opponent and have removed them from the board. Players move one piece diagonally at a time in alternating play (starting with light). All references to squares refer to the dark squares only. The board is an 8 by 8 square of squares in alternating light or dark colours. Players should set up pieces on the 12 dark squares in the first three rows closest to them (the light spaces are completely ignored in the game), setting up three rows of 4 checkers. ==Moving & Capturing in Straight Checkers== Take turns moving a checker one space diagonally forward towards the opponent's side of the board on a square that contains no checkers of either player. You may 'jump' your opponents checkers by making a capturing move if your checker is located at most one space behind your opponent's checker (on your side). When capturing you jump over the checker moving two spaces in the same direction and then remove their piece from the game. Capturing multiple pieces using multiple jumps in the same turn is a key part of the game, when doing so you may change which direction they're moving diagonally, but they must still always move forward. :* If you have the opportunity to jump your opponent's checker, you must. :* You may continue capturing subsequent checkers until there are no more possible captures. :* If you have the opportunity to jump a choice of opponent's checkers, you may choose which but must capture one of them. ==Kings in Straight Checkers== When one of your pieces reaches the end of the opponent's board that piece is upgraded to a king, these may move in either direction now. :* Kings may move forward or backward diagonally. :* Kings can still only move one diagonal space at a time unless capturing. :* Kings may move both forward and backward in the same turn when capturing. ==Winning== Complete ''one'' of the following three objectives; :* Capture all of an opponent's pieces. '''or''' :* Block all your opponent's pieces so they can't make any more moves. '''or''' :* Have all your pieces on the opponent's far end of the board (your opponent will need to have captured half or more of your pieces). ==Draws== A draw is declared if ''any'' of these conditions occur; :* A game is a draw if neither opponent has the possibility to win the game. '''or''' :* The game is considered a draw when the same situation repeats itself for the third time (not necessarily consecutive). '''or''' :* A one king against one king endgame is often declared a draw. ==Strategy== :* Be aggressive, you are more likely to win. Playing to the board sides are safer though without reward. :* Forward- always forward, it's alright to lose pieces as long as you take the opponent's, save your kings. :* Safety in numbers, don't leave your pieces alone, move them one after another in small groups to protect them. :* Protect the rear, protect forward or don't move your end row pieces as long as possible to prevent opponent's kings. :* Sacrifice when needed. draw out your opponent so you can get 2-1 trades the following turn, don't expose your kings without reward. :* Each king you get is a huge bonus, try to get as many as possible and don't waste them, sacrificing several pieces for a king can be alright. :* Don't forget to block your opponent when possible, you make not only that piece vulnerable but fail to protect it with a counter and give your opponent the chance to take multiple of your pieces in one turn. 0a20ff1351a1f247596699239c78b3db2892f3fa 1276 1258 2014-10-26T20:38:54Z Een 3 Make the description more accurate for BGA implementation wikitext text/x-wiki == Objective of the Game == Checkers, also known as 'draughts', is a timeless abstract strategy game for two players dating back almost a thousand years. In the game you move your pieces until you've jumped over all pieces of your opponent and have removed them from the board. Players move one piece diagonally at a time in alternating play (starting with light). All references to squares refer to the dark squares only. The board is an 8 by 8 square of squares in alternating light or dark colours. Players should set up pieces on the 12 dark squares in the first three rows closest to them (the light spaces are completely ignored in the game), setting up three rows of 4 checkers. == Game variants == There is a lot of Checkers variants. Four of them are available on Board Game Arena : :* International Checkers :* Straight Checkers :* Brazilian Checkers :* Russian Checkers. Make sure to check the rules for the variant you are currently playing: the following section applies only to Straight Checkers. == Straight Checkers == ===Moving & Capturing=== Take turns moving a checker one space diagonally forward towards the opponent's side of the board on a square that contains no checkers of either player. You may 'jump' your opponents checkers by making a capturing move if your checker is located at most one space behind your opponent's checker (on your side). When capturing you jump over the checker moving two spaces in the same direction and then remove their piece from the game. Capturing multiple pieces using multiple jumps in the same turn is a key part of the game, when doing so you may change which direction they're moving diagonally, but they must still always move forward. :* If you have the opportunity to jump your opponent's checker, you must. :* You may continue capturing subsequent checkers until there are no more possible captures. :* If you have the opportunity to jump a choice of opponent's checkers, you may choose which but must capture one of them. ===Kings=== When one of your pieces reaches the end of the opponent's board that piece is upgraded to a king, these may move in either direction now. :* Kings may move forward or backward diagonally. :* Kings can still only move one diagonal space at a time unless capturing. :* Kings may move both forward and backward in the same turn when capturing. ==Winning== Complete ''one'' of the following two objectives; :* Capture all of your opponent's pieces. '''or''' :* Block all your opponent's pieces so they can't make any more moves. ==Draws== A draw is declared if ''any'' of these conditions occur; :* The same situation repeats itself for the third time (not necessarily consecutive). '''or''' :* 25 moves have been played without moving a man forward or making a capture. ==Strategy== :* Be aggressive, you are more likely to win. Playing to the board sides are safer though without reward. :* Forward- always forward, it's alright to lose pieces as long as you take the opponent's, save your kings. :* Safety in numbers, don't leave your pieces alone, move them one after another in small groups to protect them. :* Protect the rear, protect forward or don't move your end row pieces as long as possible to prevent opponent's kings. :* Sacrifice when needed. draw out your opponent so you can get 2-1 trades the following turn, don't expose your kings without reward. :* Each king you get is a huge bonus, try to get as many as possible and don't waste them, sacrificing several pieces for a king can be alright. :* Don't forget to block your opponent when possible, you make not only that piece vulnerable but fail to protect it with a counter and give your opponent the chance to take multiple of your pieces in one turn. 7b9f8be2ce9ed4b221b453570407a8f542b405b8 1277 1276 2014-10-26T20:47:34Z Een 3 /* Game variants */ wikitext text/x-wiki == Objective of the Game == Checkers, also known as 'draughts', is a timeless abstract strategy game for two players dating back almost a thousand years. In the game you move your pieces until you've jumped over all pieces of your opponent and have removed them from the board. Players move one piece diagonally at a time in alternating play (starting with light). All references to squares refer to the dark squares only. The board is an 8 by 8 square of squares in alternating light or dark colours. Players should set up pieces on the 12 dark squares in the first three rows closest to them (the light spaces are completely ignored in the game), setting up three rows of 4 checkers. == Game variants == There is a lot of Checkers variants. Four of them are available on Board Game Arena : :* International Checkers (10x10 board, men can capture backwards, kings can fly, one must capture as many pieces as possible) :* Straight Checkers (8x8 board, men cannot capture backwards, kings can capture backwards but not fly, one must capture if possible but not necessarily as many pieces as possible) :* Brazilian Checkers (8x8 board, men can capture backwards, kings can fly, one must capture as many pieces as possible) :* Russian Checkers (8x8 board, men can capture backwards, kings can fly and go on capturing immediately after getting crowned, one must capture if possible but not necessarily as many pieces as possible). Make sure to check the rules for the variant you are currently playing: the following detailed section applies only to Straight Checkers. == Straight Checkers == ===Moving & Capturing=== Take turns moving a checker one space diagonally forward towards the opponent's side of the board on a square that contains no checkers of either player. You may 'jump' your opponents checkers by making a capturing move if your checker is located at most one space behind your opponent's checker (on your side). When capturing you jump over the checker moving two spaces in the same direction and then remove their piece from the game. Capturing multiple pieces using multiple jumps in the same turn is a key part of the game, when doing so you may change which direction they're moving diagonally, but they must still always move forward. :* If you have the opportunity to jump your opponent's checker, you must. :* You may continue capturing subsequent checkers until there are no more possible captures. :* If you have the opportunity to jump a choice of opponent's checkers, you may choose which but must capture one of them. ===Kings=== When one of your pieces reaches the end of the opponent's board that piece is upgraded to a king, these may move in either direction now. :* Kings may move forward or backward diagonally. :* Kings can still only move one diagonal space at a time unless capturing. :* Kings may move both forward and backward in the same turn when capturing. ==Winning== Complete ''one'' of the following two objectives; :* Capture all of your opponent's pieces. '''or''' :* Block all your opponent's pieces so they can't make any more moves. ==Draws== A draw is declared if ''any'' of these conditions occur; :* The same situation repeats itself for the third time (not necessarily consecutive). '''or''' :* 25 moves have been played without moving a man forward or making a capture. ==Strategy== :* Be aggressive, you are more likely to win. Playing to the board sides are safer though without reward. :* Forward- always forward, it's alright to lose pieces as long as you take the opponent's, save your kings. :* Safety in numbers, don't leave your pieces alone, move them one after another in small groups to protect them. :* Protect the rear, protect forward or don't move your end row pieces as long as possible to prevent opponent's kings. :* Sacrifice when needed. draw out your opponent so you can get 2-1 trades the following turn, don't expose your kings without reward. :* Each king you get is a huge bonus, try to get as many as possible and don't waste them, sacrificing several pieces for a king can be alright. :* Don't forget to block your opponent when possible, you make not only that piece vulnerable but fail to protect it with a counter and give your opponent the chance to take multiple of your pieces in one turn. 882bc981b83b3dc21130ca66fd20cdf58ec9de5f 1278 1277 2014-10-26T20:48:05Z Een 3 /* Game variants */ wikitext text/x-wiki == Objective of the Game == Checkers, also known as 'draughts', is a timeless abstract strategy game for two players dating back almost a thousand years. In the game you move your pieces until you've jumped over all pieces of your opponent and have removed them from the board. Players move one piece diagonally at a time in alternating play (starting with light). All references to squares refer to the dark squares only. The board is an 8 by 8 square of squares in alternating light or dark colours. Players should set up pieces on the 12 dark squares in the first three rows closest to them (the light spaces are completely ignored in the game), setting up three rows of 4 checkers. == Game variants == There is a lot of Checkers variants. Four of them are available on Board Game Arena : :* International Checkers (10x10 board, men can capture backwards, kings can fly, one must capture as many pieces as possible) :* Straight Checkers (8x8 board, men cannot capture backwards, kings can capture backwards but cannot fly, one must capture if possible but not necessarily as many pieces as possible) :* Brazilian Checkers (8x8 board, men can capture backwards, kings can fly, one must capture as many pieces as possible) :* Russian Checkers (8x8 board, men can capture backwards, kings can fly and go on capturing immediately after getting crowned, one must capture if possible but not necessarily as many pieces as possible). Make sure to check the rules for the variant you are currently playing: the following detailed section applies only to Straight Checkers. == Straight Checkers == ===Moving & Capturing=== Take turns moving a checker one space diagonally forward towards the opponent's side of the board on a square that contains no checkers of either player. You may 'jump' your opponents checkers by making a capturing move if your checker is located at most one space behind your opponent's checker (on your side). When capturing you jump over the checker moving two spaces in the same direction and then remove their piece from the game. Capturing multiple pieces using multiple jumps in the same turn is a key part of the game, when doing so you may change which direction they're moving diagonally, but they must still always move forward. :* If you have the opportunity to jump your opponent's checker, you must. :* You may continue capturing subsequent checkers until there are no more possible captures. :* If you have the opportunity to jump a choice of opponent's checkers, you may choose which but must capture one of them. ===Kings=== When one of your pieces reaches the end of the opponent's board that piece is upgraded to a king, these may move in either direction now. :* Kings may move forward or backward diagonally. :* Kings can still only move one diagonal space at a time unless capturing. :* Kings may move both forward and backward in the same turn when capturing. ==Winning== Complete ''one'' of the following two objectives; :* Capture all of your opponent's pieces. '''or''' :* Block all your opponent's pieces so they can't make any more moves. ==Draws== A draw is declared if ''any'' of these conditions occur; :* The same situation repeats itself for the third time (not necessarily consecutive). '''or''' :* 25 moves have been played without moving a man forward or making a capture. ==Strategy== :* Be aggressive, you are more likely to win. Playing to the board sides are safer though without reward. :* Forward- always forward, it's alright to lose pieces as long as you take the opponent's, save your kings. :* Safety in numbers, don't leave your pieces alone, move them one after another in small groups to protect them. :* Protect the rear, protect forward or don't move your end row pieces as long as possible to prevent opponent's kings. :* Sacrifice when needed. draw out your opponent so you can get 2-1 trades the following turn, don't expose your kings without reward. :* Each king you get is a huge bonus, try to get as many as possible and don't waste them, sacrificing several pieces for a king can be alright. :* Don't forget to block your opponent when possible, you make not only that piece vulnerable but fail to protect it with a counter and give your opponent the chance to take multiple of your pieces in one turn. 952a974587e6ed2bc2028d792e2b2c8f9c694782 Multipleaccounts 0 164 1259 1215 2014-10-21T09:02:25Z Micke 1830 /* Playing from the same IP */ wikitext text/x-wiki == The Main Rule == '''One BGA account = One person''' == Playing from the same IP == This is '''authorized''' to play at the same table from the same IP (internet address). The warning message "this player plays from the same internet address as another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game. If you want to play from the same internet address as another person: * The best option is not to play at the same table, or play at a table where you know everyone. * If you play with strangers, make them comfortable with the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner. When some of your opponents are playing from the same IP: * You may politely refuse to play with them. * You should be vigilant and check that they are not collaborating during the game. * You don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report. == Boosting your ELO by playing against yourself == This is the most stupid and useless thing to do on BGA. Why? Because this is very easy to detect, and because the penalty is: * all your secondary account are removed. * your primary account is reset to 1500 ELO for all games. Why this is so easy to detect: * When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO. * In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game. * In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account". * Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless. If you have a lot of time to spend, please try to get better at this game and please do not try to cheat. fbe0ce289d212cdf11b884f5b698abd6188f44af Gamehelpdudo 0 165 1260 1190 2014-10-21T09:07:59Z Mennoknight 6638 wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Round order=== All players roll their dice and check what they rolled. The first player (randomly selected) starts with an opening bid; he proclaims a die value and the amount of dice in the playfield having this exact value. He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos, unless a player is Palifico. After a bid is placed, the turn is passed on to the player on his left, this player has 2 options: # If he thinks that the last bid was wrong he can say "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players must reveal their dice. All dice that match the bid are counted.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game. ====Option 2: increasing the bid==== To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same # increase the value on the die, thus the number of dice stays the same Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts. ===Special rules=== The side of the die with the paco on is special This side counts as a joker for the number of eyes when a Dudo is called. As example: The bid on which a Dudo was called is: 9 dice with a value of 3. {| class="wikitable" style="width: 300px;" |+These dice are on the table |- ! ! colspan="6" | Dice Faces |- ! Player ! Paco ! 2 ! 3 ! 4 ! 5 ! 6 |- | Mike ||1 ||2 ||1 ||0 ||0 ||1 |- | Lucy ||0 ||3 ||1 ||1 ||0 ||0 |- | John ||3 ||0 ||1 ||0 ||0 ||1 |- | Susan ||1 ||0 ||1 ||1 ||1 ||1 |} There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die. As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up. Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco. The Next player can now choose to either # Increase the number of dice with a paco # Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra. Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11) ===Palifico=== The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated). ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza. If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid. </li></ol> bbb0adc005e6da0280d31203e4dcafe998323017 1261 1260 2014-10-21T09:12:05Z Mennoknight 6638 /* Round order */ wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos, unless a player is Palifico. After a bid is placed, the turn is passed on to the player on his left, this player has 2 options: # If he thinks that the last bid was wrong he can say "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players must reveal their dice. All dice that match the bid are counted.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game. ====Option 2: increasing the bid==== To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same # increase the value on the die, thus the number of dice stays the same Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts. ===Special rules=== The side of the die with the paco on is special This side counts as a joker for the number of eyes when a Dudo is called. As example: The bid on which a Dudo was called is: 9 dice with a value of 3. {| class="wikitable" style="width: 300px;" |+These dice are on the table |- ! ! colspan="6" | Dice Faces |- ! Player ! Paco ! 2 ! 3 ! 4 ! 5 ! 6 |- | Mike ||1 ||2 ||1 ||0 ||0 ||1 |- | Lucy ||0 ||3 ||1 ||1 ||0 ||0 |- | John ||3 ||0 ||1 ||0 ||0 ||1 |- | Susan ||1 ||0 ||1 ||1 ||1 ||1 |} There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die. As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up. Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco. The Next player can now choose to either # Increase the number of dice with a paco # Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra. Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11) ===Palifico=== The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated). ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza. If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid. </li></ol> 7b90aa9d078fea146aee3f059d5199fdbfb667f1 1262 1261 2014-10-21T09:15:22Z Mennoknight 6638 /* Playing a Round */ wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. '''This bid takes into account all of the dice on the table.''' He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos (ones), unless a player is Palifico. After a bid is placed, the turn is passed on to the player on his left. This player has 2 options: # If he thinks that the last bid was wrong he can call "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players reveal their dice. All dice that match the bid are counted.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game. ====Option 2: increasing the bid==== To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same # increase the value on the die, thus the number of dice stays the same Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts. ===Special rules=== The side of the die with the paco on is special This side counts as a joker for the number of eyes when a Dudo is called. As example: The bid on which a Dudo was called is: 9 dice with a value of 3. {| class="wikitable" style="width: 300px;" |+These dice are on the table |- ! ! colspan="6" | Dice Faces |- ! Player ! Paco ! 2 ! 3 ! 4 ! 5 ! 6 |- | Mike ||1 ||2 ||1 ||0 ||0 ||1 |- | Lucy ||0 ||3 ||1 ||1 ||0 ||0 |- | John ||3 ||0 ||1 ||0 ||0 ||1 |- | Susan ||1 ||0 ||1 ||1 ||1 ||1 |} There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die. As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up. Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco. The Next player can now choose to either # Increase the number of dice with a paco # Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra. Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11) ===Palifico=== The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated). ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza. If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid. </li></ol> 496a8d0cbdac17324015bd0a85baf7d4bdea2cb5 1263 1262 2014-10-21T09:20:19Z Mennoknight 6638 /* Playing a Round */ wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. '''This bid takes into account all of the dice on the table.''' He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos (ones), unless a player is Palifico. After a bid is placed, the turn is passed on to the player on his left. This player has 2 options: # If he thinks that the last bid was wrong he can call "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players reveal their dice. All dice that match the bid are counted.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game. ====Option 2: increasing the bid==== To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same # increase the value on the die, thus the number of dice stays the same Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts. ===Special rules=== The side of the die with the paco on is special This side counts as a joker for the number of eyes when a Dudo is called. As example: The bid on which a Dudo was called is: 9 dice with a value of 3. {| class="wikitable" style="width: 300px;" |+These dice are on the table |- ! ! colspan="6" | Dice Faces |- ! Player ! Paco ! 2 ! 3 ! 4 ! 5 ! 6 |- | Mike ||1 ||2 ||1 ||0 ||0 ||1 |- | Lucy ||0 ||3 ||1 ||1 ||0 ||0 |- | John ||3 ||0 ||1 ||0 ||0 ||1 |- | Susan ||1 ||0 ||1 ||1 ||1 ||1 |} There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die. As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up. Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco. The Next player can now choose to either # Increase the number of dice with a paco # Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra. Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11) ===Palifico=== The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated). ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza. If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid. </li></ol> 69452f70732d9387e224a843de465e23cc1997f1 1264 1263 2014-10-21T09:21:25Z Mennoknight 6638 /* Set up */ wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". A Paco counts as a wild card - it can count as any other number. Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. '''This bid takes into account all of the dice on the table.''' He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos (ones), unless a player is Palifico. After a bid is placed, the turn is passed on to the player on his left. This player has 2 options: # If he thinks that the last bid was wrong he can call "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players reveal their dice. All dice that match the bid are counted.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. The moment a player loses his last die, not a single die left in his hand, he is out of the game. From this point on that player does no longer participate in the game. ====Option 2: increasing the bid==== To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same # increase the value on the die, thus the number of dice stays the same Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts. ===Special rules=== The side of the die with the paco on is special This side counts as a joker for the number of eyes when a Dudo is called. As example: The bid on which a Dudo was called is: 9 dice with a value of 3. {| class="wikitable" style="width: 300px;" |+These dice are on the table |- ! ! colspan="6" | Dice Faces |- ! Player ! Paco ! 2 ! 3 ! 4 ! 5 ! 6 |- | Mike ||1 ||2 ||1 ||0 ||0 ||1 |- | Lucy ||0 ||3 ||1 ||1 ||0 ||0 |- | John ||3 ||0 ||1 ||0 ||0 ||1 |- | Susan ||1 ||0 ||1 ||1 ||1 ||1 |} There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die. As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up. Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco. The Next player can now choose to either # Increase the number of dice with a paco # Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra. Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11) ===Palifico=== The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated). ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza. If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid. </li></ol> 754c4bd6c33735020ef6ca8d4454fe0149e57d00 1265 1264 2014-10-21T09:31:38Z Mennoknight 6638 /* Playing a Round */ wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". A Paco counts as a wild card - it can count as any other number. Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. '''This bid takes into account all of the dice on the table.''' He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos (ones), unless a player is Palifico (which will be explained later). After a bid is placed, the turn is passed on to the player on his left. This player has 2 options: # If he thinks that the last bid was wrong he can call "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players reveal their dice. All dice that match the bid are counted, including Pacos.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> For example, let's say Bob calls "Dudo" on Abe's bid of four fives (four dice with the number five showing). When all the dice are revealed and counted up, there are 3 fives and 2 pacos. This counts as 5 fives, so Abe was safe with his bid. Bob loses a die for the rest of the game. '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. If Abe has called 6 fives instead of 3 in the same scenario, his bid is over the number of fives in play (only 5). If this is the case, Abe loses a die instead. The moment a player loses his last die, that player is out of the game. ====Option 2: increasing the bid==== If a player does not want to call Dudo, he has to make a higher bid of his own. To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same (ex. raising a bid of 2 threes with one of 3 threes) # increase the value on the die, thus the number of dice stays the same (ex. raising a bid of 2 threes with a bid of 2 fours or 2 sixes) Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts. ===Special rules=== The side of the die with the paco on is special This side counts as a joker for the number of eyes when a Dudo is called. As example: The bid on which a Dudo was called is: 9 dice with a value of 3. {| class="wikitable" style="width: 300px;" |+These dice are on the table |- ! ! colspan="6" | Dice Faces |- ! Player ! Paco ! 2 ! 3 ! 4 ! 5 ! 6 |- | Mike ||1 ||2 ||1 ||0 ||0 ||1 |- | Lucy ||0 ||3 ||1 ||1 ||0 ||0 |- | John ||3 ||0 ||1 ||0 ||0 ||1 |- | Susan ||1 ||0 ||1 ||1 ||1 ||1 |} There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die. As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up. Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco. The Next player can now choose to either # Increase the number of dice with a paco # Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra. Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11) ===Palifico=== The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated). ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza. If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid. </li></ol> b59421540ff47d681823ec3b884bfce3c9661856 1266 1265 2014-10-21T09:32:39Z Mennoknight 6638 /* Playing a Round */ wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". A Paco counts as a wild card - it can count as any other number. Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. '''This bid takes into account all of the dice on the table.''' He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos (ones), unless a player is Palifico (which will be explained later). After a bid is placed, the turn is passed on to the player on his left. This player has 2 options: # If he thinks that the last bid was wrong he can call "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players reveal their dice. All dice that match the bid are counted, including Pacos.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> For example, let's say Bob calls "Dudo" on Abe's bid of four fives (four dice with the number five showing). When all the dice are revealed and counted up, there are 3 fives and 2 pacos. This counts as 5 fives, so Abe was safe with his bid. Bob loses a die for the rest of the game. '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. If Abe has called 6 fives instead of 3 in the same scenario, his bid is over the number of fives in play (only 5). If this is the case, Abe loses a die instead. The moment a player loses his last die, that player is out of the game. ====Option 2: increasing the bid==== If a player does not want to call Dudo, he has to make a higher bid of his own. To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same (ex. raising a bid of 2 threes with one of 3 threes) # increase the value on the die, thus the number of dice stays the same (ex. raising a bid of 2 threes with a bid of 2 fours or 2 sixes) Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts. ===Special rules=== The side of the die with the paco on is special This side counts as a joker for the number of eyes when a Dudo is called. As example: The bid on which a Dudo was called is: 9 dice with a value of 3. {| class="wikitable" style="width: 300px;" |+These dice are on the table |- ! ! colspan="6" | Dice Faces |- ! Player ! Paco ! 2 ! 3 ! 4 ! 5 ! 6 |- | Mike ||1 ||2 ||1 ||0 ||0 ||1 |- | Lucy ||0 ||3 ||1 ||1 ||0 ||0 |- | John ||3 ||0 ||1 ||0 ||0 ||1 |- | Susan ||1 ||0 ||1 ||1 ||1 ||1 |} There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die. As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up. Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco. The Next player can now choose to either # Increase the number of dice with a paco # Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra. Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11) ===Palifico=== The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated). ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza. If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid. </li></ol> 5710f2ff8f00f4ff919f856f5782f2492c97830a 1267 1266 2014-10-21T09:32:50Z Mennoknight 6638 /* Playing a Round */ wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". A Paco counts as a wild card - it can count as any other number. Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. '''This bid takes into account all of the dice on the table.''' He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos (ones), unless a player is Palifico (which will be explained later). After a bid is placed, the turn is passed on to the player on his left. This player has 2 options: # If he thinks that the last bid was wrong he can call "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players reveal their dice. All dice that match the bid are counted, including Pacos.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> For example, let's say Bob calls "Dudo" on Abe's bid of four fives (four dice with the number five showing). When all the dice are revealed and counted up, there are 3 fives and 2 pacos. This counts as 5 fives, so Abe was safe with his bid. Bob loses a die for the rest of the game. '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. If Abe has called 6 fives instead of 3 in the same scenario, his bid is over the number of fives in play (only 5). If this is the case, Abe loses a die instead. The moment a player loses his last die, that player is out of the game. ====Option 2: increasing the bid==== If a player does not want to call Dudo, he has to make a higher bid of his own. To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same (ex. raising a bid of 2 threes with one of 3 threes) # increase the value on the die, thus the number of dice stays the same (ex. raising a bid of 2 threes with a bid of 2 fours or 2 sixes) Once a new bid has been established the turn is passed on to the next player to the left etc. When Dudo has been called and a player lost a die, the player that lost his die starts a new round. Or if the player that lost a die lost his last die the player left of the eliminated player starts. ===Special rules=== The side of the die with the paco on is special This side counts as a joker for the number of eyes when a Dudo is called. As example: The bid on which a Dudo was called is: 9 dice with a value of 3. {| class="wikitable" style="width: 300px;" |+These dice are on the table |- ! ! colspan="6" | Dice Faces |- ! Player ! Paco ! 2 ! 3 ! 4 ! 5 ! 6 |- | Mike ||1 ||2 ||1 ||0 ||0 ||1 |- | Lucy ||0 ||3 ||1 ||1 ||0 ||0 |- | John ||3 ||0 ||1 ||0 ||0 ||1 |- | Susan ||1 ||0 ||1 ||1 ||1 ||1 |} There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die. As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up. Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco. The Next player can now choose to either # Increase the number of dice with a paco # Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra. Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11) ===Palifico=== The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated). ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza. If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid. </li></ol> 49ae5a0d1d843f7bf898de9eb2907ebf347dd135 1268 1267 2014-10-21T09:40:02Z Mennoknight 6638 /* Option 2: increasing the bid */ wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". A Paco counts as a wild card - it can count as any other number. Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. '''This bid takes into account all of the dice on the table.''' He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos (ones), unless a player is Palifico (which will be explained later). After a bid is placed, the turn is passed on to the player on his left. This player has 2 options: # If he thinks that the last bid was wrong he can call "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players reveal their dice. All dice that match the bid are counted, including Pacos.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> For example, let's say Bob calls "Dudo" on Abe's bid of four fives (four dice with the number five showing). When all the dice are revealed and counted up, there are 3 fives and 2 pacos. This counts as 5 fives, so Abe was safe with his bid. Bob loses a die for the rest of the game. '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. If Abe has called 6 fives instead of 3 in the same scenario, his bid is over the number of fives in play (only 5). If this is the case, Abe loses a die instead. The moment a player loses his last die, that player is out of the game. ====Option 2: increasing the bid==== If a player does not want to call Dudo, he has to make a higher bid of his own. To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same (ex. raising a bid of 2 threes with one of 3 threes) # increase the value on the die, thus the number of dice stays the same (ex. raising a bid of 2 threes with a bid of 2 fours or 2 sixes) Once a new bid has been established the turn is passed on to the next player to the left, and play continues until someone calls Dudo. When Dudo has been called and a player loses a die, the player that lost his die starts a new round. If the player that lost a die is out, the player to the left of the eliminated player starts the next round instead.. ===Special rules=== The side of the die with the paco on is special This side counts as a joker for the number of eyes when a Dudo is called. As example: The bid on which a Dudo was called is: 9 dice with a value of 3. {| class="wikitable" style="width: 300px;" |+These dice are on the table |- ! ! colspan="6" | Dice Faces |- ! Player ! Paco ! 2 ! 3 ! 4 ! 5 ! 6 |- | Mike ||1 ||2 ||1 ||0 ||0 ||1 |- | Lucy ||0 ||3 ||1 ||1 ||0 ||0 |- | John ||3 ||0 ||1 ||0 ||0 ||1 |- | Susan ||1 ||0 ||1 ||1 ||1 ||1 |} There are thus 4 dice with a value of 3. However, there are also 5 pacos as these count as jokers<br/>we add them to the 4 dice with a value of 3 to get a total of 9 dice with a value of 3. <br/>The Bid is thus valid and the player who called Dudo loses a die. As pointed out above an opening bid cannot be based on pacos, '''unless''' a player reached Palifico (more below). However, during the game you can make a bid of pacos. This is the only exception to the rule you always have to upbid. As placing a bid of pacos provides a way to decrease the amount of dice. To place a bid with pacos the number of dice is divided in half, rounded up. Example: from 9 dice with a value of 3 one can make a bid of 5 <br/> (9/2=4.5 -rounding up->5) dice with a paco. The Next player can now choose to either # Increase the number of dice with a paco # Increase the value on the die. In order to do this his bid of dice must be at least the double amount of the last bid with pacos while adding one extra. Example: So from 5 dice with paco he could go to 11 (5*2+1=11) dice with value 3. <br/>(or thus any number of dice exceeding 11) ===Palifico=== The moment a player has only one die remaining this player has reached Palifico. During the next round the Pacos do not count as jokers and an opening bid with paco's can be placed. '''Important''': during this round the value cannot be increased during bids. Solely the amount of dice can be increased until a Dudo is called. The player loses his Palifico state once the first round where he had a single die ends. Meaning that the next round is a normal round again eventhough the player only has 1 die (if he did not get eliminated). ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before a player places a new bid. Everyone around the table, with the exception of the player that placed the last bid, is able to call out calza. If the player that called out Calza was correct he regains one of his lost dice. However, if he was wrong he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice have yet quite the game and thus what would be the max you could bid. </li></ol> 0b607ee5afe49181b7e834d6330488e9bcebdad0 1269 1268 2014-10-21T10:09:55Z Mennoknight 6638 Did some rearranging to make the rules flow better, and make the English a little easier to understand. wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". A Paco counts as a wild card or joker - it can count as any other number. (On BGA, the Pacos are birds on the dice.) Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. '''This bid takes into account all of the dice on the table.''' He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos (ones), unless a player is Palifico (which will be explained later). After a bid is placed, the turn is passed on to the player on his left. This player has 2 options: # If he thinks that the last bid was wrong he can call "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players reveal their dice. All dice that match the bid are counted, including Pacos.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> For example, let's say Bob calls "Dudo" on Abe's bid of four fives (four dice with the number five showing). When all the dice are revealed and counted up, there are 3 fives and 2 pacos. This counts as 5 fives, so Abe was safe with his bid. Bob loses a die for the rest of the game. '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. If Abe has called 6 fives instead of 3 in the same scenario, his bid is over the number of fives in play (only 5). If this is the case, Abe loses a die instead. The moment a player loses his last die, that player is out of the game. ====Option 2: increasing the bid==== If a player does not want to call Dudo, he has to make a higher bid of his own. To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same (ex. raising a bid of 2 threes with one of 3 threes) # increase the value on the die, thus the number of dice stays the same (ex. raising a bid of 2 threes with a bid of 2 fours or 2 sixes) # reset the value on the die by choosing Pacos. To do this, the number of Pacos bid has to be at least half the number of dice currently bid, rounded up. (ex. replacing a bid of 5 sixes with 3 Pacos) # raise the value from a Paco to another number. To do this, the number of dice bid needs to be at least double the number of Pacos plus one. (ex. replacing a bid of 3 Pacos with 7 threes) Changing the bid to Pacos is a way to make lower die values reachable again, at the expense of quickly raising the number of dice being bid. Once a new bid has been established the turn is passed on to the next player to the left, and play continues until someone calls Dudo. When Dudo has been called and a player loses a die, the player that lost his die starts a new round. If the player that lost a die is out, the player to the left of the eliminated player starts the next round instead. ===Palifico=== The moment a player has only one die remaining, this player has reached Palifico. This triggers a special round. During this round, Pacos no longer count as jokers, and an opening bid can be of Pacos. '''However''': during this round the value on the dice cannot be increased during bids. The value of the dice is locked in until someone calls Dudo. After this round, the game returns to normal, regardless of whether the Palifico player still has one die left. ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before another player places a new bid or calls Dudo. Anyone around the table (except the player who made the bid) is allowed to call out Calza. If the player that called out Calza was correct (the bid is exactly the same as the number of dice on the table) he regains one of his lost dice (if the player only had one die, then the next time they fall to having only one die will '''NOT''' trigger another Palifico round. One per player per game.). However, if he was wrong, he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice are still in the game, which helps to inform how high one can reasonably bid. </li></ol> d44e097ad4ffc318f5eb429bcf21df304c11735b 1270 1269 2014-10-21T10:12:12Z Mennoknight 6638 wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". A Paco counts as a wild card or joker - it can count as any other number. (On BGA, the Pacos are birds on the dice.) Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. '''This bid takes into account all of the dice on the table.''' He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos (ones), unless a player is Palifico (which will be explained later). After a bid is placed, the turn is passed on to the player on his left. This player has 2 options: # If he thinks that the last bid was wrong he can call "Dudo" (i doubt) # If he thinks the last bid is reasonable, then he must increase the last bid. ===Option 1: calling Dudo=== As soon as Dudo is called all players reveal their dice. All dice that match the bid are counted, including Pacos.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> For example, let's say Bob calls "Dudo" on Abe's bid of four fives (four dice with the number five showing). When all the dice are revealed and counted up, there are 3 fives and 2 pacos. This counts as 5 fives, so Abe was safe with his bid. Bob loses a die for the rest of the game. '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. If Abe has called 6 fives instead of 3 in the same scenario, his bid is over the number of fives in play (only 5). If this is the case, Abe loses a die instead. The moment a player loses his last die, that player is out of the game. ===Option 2: increasing the bid=== If a player does not want to call Dudo, he has to make a higher bid of his own. To increase a bid a player has to choose one of the following options: # increase the number of dice, thus the value stays the same (ex. raising a bid of 2 threes with one of 3 threes) # increase the value on the die, thus the number of dice stays the same (ex. raising a bid of 2 threes with a bid of 2 fours or 2 sixes) # reset the value on the die by choosing Pacos. To do this, the number of Pacos bid has to be at least half the number of dice currently bid, rounded up. (ex. replacing a bid of 5 sixes with 3 Pacos) # raise the value from a Paco to another number. To do this, the number of dice bid needs to be at least double the number of Pacos plus one. (ex. replacing a bid of 3 Pacos with 7 threes) Changing the bid to Pacos is a way to make lower die values reachable again, at the expense of quickly raising the number of dice being bid. Once a new bid has been established the turn is passed on to the next player to the left, and play continues until someone calls Dudo. When Dudo has been called and a player loses a die, the player that lost his die starts a new round. If the player that lost a die is out, the player to the left of the eliminated player starts the next round instead. ===Palifico=== The moment a player has only one die remaining, this player has reached Palifico. This triggers a special round. During this round, Pacos no longer count as jokers, and an opening bid can be of Pacos. '''However''': during this round the value on the dice cannot be increased during bids. The value of the dice is locked in until someone calls Dudo. After this round, the game returns to normal, regardless of whether the Palifico player still has one die left. ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before another player places a new bid or calls Dudo. Anyone around the table (except the player who made the bid) is allowed to call out Calza. If the player that called out Calza was correct (the bid is exactly the same as the number of dice on the table) he regains one of his lost dice (if the player only had one die, then the next time they fall to having only one die will '''NOT''' trigger another Palifico round. One per player per game.). However, if he was wrong, he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice are still in the game, which helps to inform how high one can reasonably bid. </li></ol> f44a7f9116203904db3e99e56ff7684f4c67ef12 1271 1270 2014-10-21T10:15:22Z Mennoknight 6638 wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". A Paco counts as a wild card or joker - it can count as any other number. (On BGA, the Pacos are birds on the dice.) Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. '''This bid takes into account all of the dice on the table.''' He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos (ones), unless a player is Palifico (which will be explained later). After a bid is placed, the turn is passed on to the player on his left. This player has 2 options: 1. If he thinks that the last bid was wrong he can call "Dudo" (i doubt) 2. If he thinks the last bid is reasonable, then he must increase the last bid. ==='''Option 1: calling Dudo'''=== As soon as Dudo is called all players reveal their dice. All dice that match the bid are counted, including Pacos.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> For example, let's say Bob calls "Dudo" on Abe's bid of four fives (four dice with the number five showing). When all the dice are revealed and counted up, there are 3 fives and 2 pacos. This counts as 5 fives, so Abe was safe with his bid. Bob loses a die for the rest of the game. '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. If Abe has called 6 fives instead of 3 in the same scenario, his bid is over the number of fives in play (only 5). If this is the case, Abe loses a die instead. The moment a player loses his last die, that player is out of the game. ==='''Option 2: increasing the bid'''=== If a player does not want to call Dudo, he has to make a higher bid of his own. To increase a bid a player has to choose one of the following options: 1. increase the number of dice, thus the value stays the same (ex. raising a bid of 2 threes with one of 3 threes) 2. increase the value on the die, thus the number of dice stays the same (ex. raising a bid of 2 threes with a bid of 2 fours or 2 sixes) 3. reset the value on the die by choosing Pacos. To do this, the number of Pacos bid has to be at least half the number of dice currently bid, rounded up. (ex. replacing a bid of 5 sixes with 3 Pacos) 4. raise the value from a Paco to another number. To do this, the number of dice bid needs to be at least double the number of Pacos plus one. (ex. replacing a bid of 3 Pacos with 7 threes) Changing the bid to Pacos is a way to make lower die values reachable again, at the expense of quickly raising the number of dice being bid. Once a new bid has been established the turn is passed on to the next player to the left, and play continues until someone calls Dudo. When Dudo has been called and a player loses a die, the player that lost his die starts a new round. If the player that lost a die is out, the player to the left of the eliminated player starts the next round instead. ===Palifico=== The moment a player has only one die remaining, this player has reached Palifico. This triggers a special round. During this round, Pacos no longer count as jokers, and an opening bid can be of Pacos. '''However''': during this round the value on the dice cannot be increased during bids. The value of the dice is locked in until someone calls Dudo. After this round, the game returns to normal, regardless of whether the Palifico player still has one die left. ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before another player places a new bid or calls Dudo. Anyone around the table (except the player who made the bid) is allowed to call out Calza. If the player that called out Calza was correct (the bid is exactly the same as the number of dice on the table) he regains one of his lost dice (if the player only had one die, then the next time they fall to having only one die will '''NOT''' trigger another Palifico round. One per player per game.). However, if he was wrong, he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice are still in the game, which helps to inform how high one can reasonably bid. </li></ol> fa250d3e913a281d942ace05a30c18e5adc42c71 1272 1271 2014-10-21T10:16:04Z Mennoknight 6638 wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". A Paco counts as a wild card or joker - it can count as any other number. (On BGA, the Pacos are birds on the dice.) Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. '''This bid takes into account all of the dice on the table.''' He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos (ones), unless a player is Palifico (which will be explained later). After a bid is placed, the turn is passed on to the player on his left. This player has 2 options: 1. If he thinks that the last bid was wrong he can call "Dudo" (i doubt) 2. If he thinks the last bid is reasonable, then he must increase the last bid. '''Option 1: calling Dudo''' As soon as Dudo is called all players reveal their dice. All dice that match the bid are counted, including Pacos.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> For example, let's say Bob calls "Dudo" on Abe's bid of four fives (four dice with the number five showing). When all the dice are revealed and counted up, there are 3 fives and 2 pacos. This counts as 5 fives, so Abe was safe with his bid. Bob loses a die for the rest of the game. '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. If Abe has called 6 fives instead of 3 in the same scenario, his bid is over the number of fives in play (only 5). If this is the case, Abe loses a die instead. The moment a player loses his last die, that player is out of the game. '''Option 2: increasing the bid''' If a player does not want to call Dudo, he has to make a higher bid of his own. To increase a bid a player has to choose one of the following options: 1. increase the number of dice, thus the value stays the same (ex. raising a bid of 2 threes with one of 3 threes) 2. increase the value on the die, thus the number of dice stays the same (ex. raising a bid of 2 threes with a bid of 2 fours or 2 sixes) 3. reset the value on the die by choosing Pacos. To do this, the number of Pacos bid has to be at least half the number of dice currently bid, rounded up. (ex. replacing a bid of 5 sixes with 3 Pacos) 4. raise the value from a Paco to another number. To do this, the number of dice bid needs to be at least double the number of Pacos plus one. (ex. replacing a bid of 3 Pacos with 7 threes) Changing the bid to Pacos is a way to make lower die values reachable again, at the expense of quickly raising the number of dice being bid. Once a new bid has been established the turn is passed on to the next player to the left, and play continues until someone calls Dudo. When Dudo has been called and a player loses a die, the player that lost his die starts a new round. If the player that lost a die is out, the player to the left of the eliminated player starts the next round instead. ===Palifico=== The moment a player has only one die remaining, this player has reached Palifico. This triggers a special round. During this round, Pacos no longer count as jokers, and an opening bid can be of Pacos. '''However''': during this round the value on the dice cannot be increased during bids. The value of the dice is locked in until someone calls Dudo. After this round, the game returns to normal, regardless of whether the Palifico player still has one die left. ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before another player places a new bid or calls Dudo. Anyone around the table (except the player who made the bid) is allowed to call out Calza. If the player that called out Calza was correct (the bid is exactly the same as the number of dice on the table) he regains one of his lost dice (if the player only had one die, then the next time they fall to having only one die will '''NOT''' trigger another Palifico round. One per player per game.). However, if he was wrong, he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice are still in the game, which helps to inform how high one can reasonably bid. </li></ol> cf40826221b6dcfe69d7ab63d47b678450af40f3 1273 1272 2014-10-21T10:17:49Z Mennoknight 6638 wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". A Paco counts as a wild card or joker - it can count as any other number. (On BGA, the Pacos are birds on the dice.) Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. '''This bid takes into account all of the dice on the table.''' He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos (ones), unless a player is Palifico (which will be explained later). After a bid is placed, the turn is passed on to the player on his left. This player has 2 options: 1. If he thinks that the last bid was wrong he can call "Dudo" (i doubt) 2. If he thinks the last bid is reasonable, then he must increase the last bid. ===Option 1: calling Dudo=== As soon as Dudo is called all players reveal their dice. All dice that match the bid are counted, including Pacos.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> For example, let's say Bob calls "Dudo" on Abe's bid of four fives (four dice with the number five showing). When all the dice are revealed and counted up, there are 3 fives and 2 pacos. This counts as 5 fives, so Abe was safe with his bid. Bob loses a die for the rest of the game. '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. If Abe has called 6 fives instead of 3 in the same scenario, his bid is over the number of fives in play (only 5). If this is the case, Abe loses a die instead. The moment a player loses his last die, that player is out of the game. ===Option 2: increasing the bid=== If a player does not want to call Dudo, he has to make a higher bid of his own. To increase a bid a player has to choose one of the following options: 1. increase the number of dice, thus the value stays the same (ex. raising a bid of 2 threes with one of 3 threes) 2. increase the value on the die, thus the number of dice stays the same (ex. raising a bid of 2 threes with a bid of 2 fours or 2 sixes) 3. reset the value on the die by choosing Pacos. To do this, the number of Pacos bid has to be at least half the number of dice currently bid, rounded up. (ex. replacing a bid of 5 sixes with 3 Pacos) 4. raise the value from a Paco to another number. To do this, the number of dice bid needs to be at least double the number of Pacos plus one. (ex. replacing a bid of 3 Pacos with 7 threes) Changing the bid to Pacos is a way to make lower die values reachable again, at the expense of quickly raising the number of dice being bid. Once a new bid has been established the turn is passed on to the next player to the left, and play continues until someone calls Dudo. When Dudo has been called and a player loses a die, the player that lost his die starts a new round. If the player that lost a die is out, the player to the left of the eliminated player starts the next round instead. ===Palifico=== The moment a player has only one die remaining, this player has reached Palifico. This triggers a special round. During this round, Pacos no longer count as jokers, and an opening bid can be of Pacos. '''However''': during this round the value on the dice cannot be increased during bids. The value of the dice is locked in until someone calls Dudo. After this round, the game returns to normal, regardless of whether the Palifico player still has one die left. ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before another player places a new bid or calls Dudo. Anyone around the table (except the player who made the bid) is allowed to call out Calza. If the player that called out Calza was correct (the bid is exactly the same as the number of dice on the table) he regains one of his lost dice (if the player only had one die, then the next time they fall to having only one die will '''NOT''' trigger another Palifico round. One per player per game.). However, if he was wrong, he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice are still in the game, which helps to inform how high one can reasonably bid. </li></ol> 206ccec5b3baf83bdc392e39d098bbdd42719ad0 1274 1273 2014-10-21T10:18:49Z Mennoknight 6638 wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". A Paco counts as a wild card or joker - it can count as any other number. (On BGA, the Pacos are birds on the dice.) Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. '''This bid takes into account all of the dice on the table.''' He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos (ones), unless a player is Palifico (which will be explained later). After a bid is placed, the turn is passed on to the player on his left. This player has 2 options: 1. If he thinks that the last bid was wrong he can call "Dudo" (i doubt) 2. If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players reveal their dice. All dice that match the bid are counted, including Pacos.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> For example, let's say Bob calls "Dudo" on Abe's bid of four fives (four dice with the number five showing). When all the dice are revealed and counted up, there are 3 fives and 2 pacos. This counts as 5 fives, so Abe was safe with his bid. Bob loses a die for the rest of the game. '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. If Abe has called 6 fives instead of 3 in the same scenario, his bid is over the number of fives in play (only 5). If this is the case, Abe loses a die instead. The moment a player loses his last die, that player is out of the game. ====Option 2: increasing the bid==== If a player does not want to call Dudo, he has to make a higher bid of his own. To increase a bid a player has to choose one of the following options: 1. increase the number of dice, thus the value stays the same (ex. raising a bid of 2 threes with one of 3 threes) 2. increase the value on the die, thus the number of dice stays the same (ex. raising a bid of 2 threes with a bid of 2 fours or 2 sixes) 3. reset the value on the die by choosing Pacos. To do this, the number of Pacos bid has to be at least half the number of dice currently bid, rounded up. (ex. replacing a bid of 5 sixes with 3 Pacos) 4. raise the value from a Paco to another number. To do this, the number of dice bid needs to be at least double the number of Pacos plus one. (ex. replacing a bid of 3 Pacos with 7 threes) Changing the bid to Pacos is a way to make lower die values reachable again, at the expense of quickly raising the number of dice being bid. Once a new bid has been established the turn is passed on to the next player to the left, and play continues until someone calls Dudo. When Dudo has been called and a player loses a die, the player that lost his die starts a new round. If the player that lost a die is out, the player to the left of the eliminated player starts the next round instead. ===Palifico=== The moment a player has only one die remaining, this player has reached Palifico. This triggers a special round. During this round, Pacos no longer count as jokers, and an opening bid can be of Pacos. '''However''': during this round the value on the dice cannot be increased during bids. The value of the dice is locked in until someone calls Dudo. After this round, the game returns to normal, regardless of whether the Palifico player still has one die left. ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before another player places a new bid or calls Dudo. Anyone around the table (except the player who made the bid) is allowed to call out Calza. If the player that called out Calza was correct (the bid is exactly the same as the number of dice on the table) he regains one of his lost dice (if the player only had one die, then the next time they fall to having only one die will '''NOT''' trigger another Palifico round. One per player per game.). However, if he was wrong, he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice are still in the game, which helps to inform how high one can reasonably bid. </li></ol> bff0947c02c111c1ef41eb7f9b265024b57249da Help 0 4 1279 1216 2014-10-30T20:00:39Z Neon 2407 /* Games */ wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcaylus|Checkers]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpeightmastersrevenge|8 Master's revenge]] * [[Gamehelpelfenland|Elfenland]] </td> <td valign="top"> * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpjaipur|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] </td> <td valign="top"> * [[Gamehelplibertalia|Koryŏ]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] </td> <td valign="top"> * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelpsechsnimmt|Take 5!]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] </td> <td valign="top"> * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> 024827c11c4bb8c06658d5b28a68b9937246201a 1280 1279 2014-10-30T20:05:29Z Neon 2407 /* Games */ wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcheckers|Checkers]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpeightmastersrevenge|8 Master's revenge]] * [[Gamehelpelfenland|Elfenland]] </td> <td valign="top"> * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpinjawara|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] </td> <td valign="top"> * [[Gamehelpkoryo|Koryŏ]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] </td> <td valign="top"> * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelpsechsnimmt|Take 5!]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] </td> <td valign="top"> * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> b8101d138a8df92b987991f9372625f9ebd0b9b2 1281 1280 2014-10-30T20:33:35Z Neon 2407 /* Games */ wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcheckers|Checkers]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpeightmastersrevenge|8 Master's Revenge]] * [[Gamehelpelfenland|Elfenland]] </td> <td valign="top"> * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpinjawara|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] </td> <td valign="top"> * [[Gamehelpkoryo|Koryŏ]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] </td> <td valign="top"> * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelpsechsnimmt|Take 5!]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] </td> <td valign="top"> * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> bb9a703f51fdeeb177f1efc41973864c4b3b17a8 1285 1281 2014-11-08T19:38:29Z Mennoknight 6638 /* Games */ added 6 nimmt to the list wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcheckers|Checkers]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpeightmastersrevenge|8 Master's Revenge]] * [[Gamehelpelfenland|Elfenland]] </td> <td valign="top"> * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpinjawara|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] </td> <td valign="top"> * [[Gamehelpkoryo|Koryŏ]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsechsnimmt|6 Nimmt!]] </td> <td valign="top"> * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelpsechsnimmt|Take 5!]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] </td> <td valign="top"> * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> cb0ee677675efd91e217819d8f028a831cfcaea5 Gamehelptokaido 0 134 1282 1226 2014-11-01T11:14:20Z Yooyou7 6711 wikitext text/x-wiki ==  Objective of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' ===Encounters=== :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - Pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object an 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. ===Farm=== :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X= Loses coins, 1= Recovers coins, 2/3/3/4= Gains double that many coins). ===Hot Springs=== :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4 points (counts for ''Bather'' accomplishment). ===Panorama=== :('''B''') There are three Panorama types and are made of 3 (Field), 4 (Mountain), or 5 (Paddy) sections. : When a player stops on a Panorama they take the first Panorama of that type that they do not have (value from 1-5) and scores that many points. Each traveler can create only a single panorama of each type and when completed can no longer stop on the spaces corresponding to that type. :('''E''') A player may instead take a Cherry Tree and gain 2 points and 1 coin. ===Temple=== :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn points. ===Village=== :('''B''') The player draws 3 Souvenir cards and can purchase 1-3 of these cards for 1-3 coins. There are four different Souvenirs and are grouped in sets. The first Souvenir in each set is worth 1 point, the next is 3 points, then 5 and 7 points. :('''E''') Acquire a Legendary Object (counts for ''Collector'' accomplishment) for 1-3 coins: :* Shodo & Emaki - For 1 coin, gain 1 point for each Souvenir or Legendary Object. Gain 1 point for each Souvenir thereafter. :* Buppatsu & Ema - For 2 coins this counts as a different Souvenir type, 5 types in a set is worth 9 points. :* Murasame & Masamune - For 3 coins, gain 8 points. ===Inns=== : All Travelers must stop at each Inn, they may not leave until all players have arrived at that Inn. : The Inns allow players to buy one unique Meal card for 1-3 coins that are worth 6 points. : When the first traveler arrives at an Inn, they draw as many Meal cards as there are players, plus 1. : As players arrive at the Inn they may buy a Meal card to add to their collection, hidden from other players. :* ''A traveler cannot taste the same culinary specialty twice during their journey.'' :* ''A traveler can never purchase more than one Meal card per Inn.'' :* ''A traveler is never obliged to purchase a Meal card.'' == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. == Extra Options == === Initation === === Return Trip === === Gastronomy === draws one less food card at inn, drawing just enough for players. === Preparations === Earns and loses coins based on order : First player earns 2 coins, second player earns 1 coin, third player has no change, remaining players get one less coin. === The New Encounters === Adds new encounter cards to the deck. === Crossroads === Allows second options on map (Cherry trees, Amulets, etc.) cb87ce241c8016c46890b2a040fb6f387b33e8b4 Gamehelpsenet 0 108 1283 716 2014-11-04T19:41:03Z Yerand 6730 /* Movement rules */ wikitext text/x-wiki == Summary == Senet ("''The Game of Passing Through the Netherworld''") is well over 5000 yrs old, and is therefore most probably the oldest boardgame ever known. It comes from the ancient Egypt, where it was used to amuse people and serve as a religional metaphor for the human souls' journey towards a blessed afterlife. Senet is an elegant and quick blocking game for 2 players, who compete against each other by moving their own pawns across a gameboard of thirty squares. Despite its old age, Senet turns out to be an amusing and tense little game for today's gamers aswell. == Goal == Move your stones (one at a time) on a reverse "S"'-shaped gametrack from the upper left to the lower right corner of the gameboard, where they can leave the gamearea. Be the first to bear all your stones off the gameboard to win! == The four "casting sticks" == The thrown sticks determine, how far you can move a stone during your turn. How to read the sticks: Count the sticks with their light sides up (results can be: 1, 2, 3 or 4). If no light sides show up at all - that's counted as a result of 5. Throwing values of 1, 4 and 5 grant Extra Turns. == Movement rules == If your stone lands on the opponent's unprotected stone, they swap places. You cannot land on a stone of your own colour. Two or more adjacent stones of the same colour protect each other. You always have to try to do a forward move. If this is not possible, you have to move one of your stones backwards. If you have NO valid moves to make at all - you lose your turn. Stones on the last 4 gamefields are never protected and cannot be moved - just borne off. == Special gamefields == * Field 26 ('The House of Beauty'): All stones must STOP here on an exact throw, before they can go further. A stone standing here can be borne off the board on an exact throw of 5. * Field 27 ('The House of Waters'): This is a pitfall! If you have a stone 'drowning' here, you have to decide whether to return the stone to Field 15 ('The House of Second Life') or to take the sticks and risk to throw a value of 4. (If you succeed to throw a 4 - the stone is borne off). * Field 28 ('The House of Three Judges'): A stone standing here, can be borne off the board by an exact throw of 3. * Field 29 ('The House of Two Judges'): A stone standing here, can be borne off the board by an exact throw of 2. * Field 30 ('The House of Horus'): A stone standing here, can be borne off the board by ANY throw. If a stone is attacked on the last 3 gamefields, it is dropped into the "water" (unless the House of Waters is occupied already). Be the first to bear all your stones off the gameboard! 4d07a0e1e1fd572957b4062a420b60ecdcaec723 Gamehelpsechsnimmt 0 174 1284 2014-11-08T19:29:01Z Mennoknight 6638 created the page! because maybe people don't want to download a .pdf or something. wikitext text/x-wiki == 6 nimmt! == The basic goal of the game is to avoid having to pick up cards, and try to force the other players to do so. Everyone starts with 66 points - you lose one for each "beef head" on a card you have to pick up. When one player has lost all of their points, the game will end at the end of the current round and the player with the most points left wins! === Playing the game === Everyone starts a round with 10 cards in their hand. Four cards are placed on the table to start four rows. Every player secretly chooses a card, and then all of the cards are revealed at the same time. When the cards are revealed, they are placed on the ends of rows following two rules: 1. cards are always placed in ascending order. 2. cards are always placed next to the card on the board with the smallest difference between them. As play progresses, the rows will fill up with cards - at five cards, a row is full. If someone's card would go onto a full row, that player has to pick up all of the cards in that row, and they lose as many points as there are "beef heads" on the cards (different cards are worth different amounts - more on that in a moment). The card that the person played becomes the starting point of a new row. If someone plays a card that is lower than then numbers at the end of all of the rows, then that player must take a row of their choice, and start a new row in its place with their card. '''Bull heads''' Each card has a number of bull heads on it - this indicates how many points it is worth when it is picked up. Cards which end in the number "5" (ex. 5, 15, 25) are worth 2 points. Cards which end in the number "0" (10, 20, 30) are worth 3 points. Cards which have double numbers (11, 22, 33) are worth 5 points. The "55" card has both a "5" and double numbers, and is worth 7 points. All other cards are worth 1 point. '''End of a round''' Once a round ends, if no one has lost all of their points, then a new round begins. If someone is out of points, then the game is over and whoever still has the most points is the winner. === Alternate Rules === '''Tactics:''' This ruleset changes the number of cards in play based on how many people are playing - other than that the rules are the same. The number of cards is equal to the number of players plus 4, so every card that could be played will find its way onto the table at some point. This changes strategy some and makes paying attention to which cards are have yet to be played important. '''Logic:''' The same as Tactics, except that at the start of the round all of the cards are placed on the table face up, and players take turns choosing cards one at a time to build their hands before the round proper starts. ed083da23989b1fb4c4554884aba19df8f70978a Gamehelphanabi 0 175 1286 2014-11-18T17:14:21Z Beri 6819 Created page with " == '''ELO rating''' == If you are playing with ELO rating on, your ELO may be changed at the end of the game. Here is how it works: 1) Every player on the team is temporari..." wikitext text/x-wiki == '''ELO rating''' == If you are playing with ELO rating on, your ELO may be changed at the end of the game. Here is how it works: 1) Every player on the team is temporarily considered as having the average ELO rating of the team. 2) The system will generate a bot associated with the score your team has achieved (let’s call it '''Hanabot'''). Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolor), the number of players on the team and, most importantly, your team's score. All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players. 3) Your team (actually your team's average ELO) will now compete against Hanabot. The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot. If your score is below 18 (50-card game) or below 21 (60-card game), your team is considered as losing against the weakest Hanabot for this configuration (variant and number of players). FYI, you can find all ELO ratings here: <link to be inserted>. The 55-card variant (50 cards + 1 of each value in the sixth colour) cannot be played with ELO rating on. This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills. A loss (3 Strike tokens) is the same as a score of 0. If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points. 78bedabf639ce6147d0599247ffabe6481e97715 1287 1286 2014-11-18T17:30:17Z Beri 6819 /* ELO rating */ wikitext text/x-wiki == '''ELO rating''' == If you are playing with ELO rating on, your ELO may be changed at the end of the game. Here is how it works: 1) Every player on the team is temporarily considered as having the average ELO rating of the team. 2) The system will generate a bot associated with the score your team has achieved (let’s call it '''Hanabot'''). Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolor), the number of players on the team and, most importantly, your team's score. All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players. 3) Your team (actually your team's average ELO) will now compete against Hanabot. The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot. If your score is below 18 (50-card game) or below 21 (60-card game), your team is considered as losing against the weakest Hanabot for this configuration (variant and number of players). FYI, you can find all bots' ELO ratings here: <link to be inserted>. The 55-card variant (50 cards + 1 of each value in the sixth colour) cannot be played with ELO rating on. This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills. A loss (3 Strike tokens) is the same as a score of 0. If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points. 7271b21bd958157332b263058f71cad50eb224bd 1288 1287 2014-11-18T20:13:21Z Sourisdudesert 1 wikitext text/x-wiki == About "cheating" == In the "real life Hanabi", you can talk. That's why we choosed to let the chat open for the online version. As a consequence, this is very easy to cheat at Hanabi. And as you can imagine, this is very stupid and this has no interest... except for ELO boosting. This is the reason why for this game there is no international ranking (ie: best player, second best player) and no trophies associated to it. == '''ELO rating''' == If you are playing with ELO rating on, your ELO may be changed at the end of the game. Here is how it works: 1) Every player on the team is temporarily considered as having the average ELO rating of the team. 2) The system will generate a bot associated with the score your team has achieved (let’s call it '''Hanabot'''). Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolor), the number of players on the team and, most importantly, your team's score. All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players. 3) Your team (actually your team's average ELO) will now compete against Hanabot. The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot. If your score is below 18 (50-card game) or below 21 (60-card game), your team is considered as losing against the weakest Hanabot for this configuration (variant and number of players). FYI, you can find all bots' ELO ratings here: <link to be inserted>. The 55-card variant (50 cards + 1 of each value in the sixth colour) cannot be played with ELO rating on. This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills. A loss (3 Strike tokens) is the same as a score of 0. If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points. 8875c517162081a3018d06db57f6427b060e7762 1289 1288 2014-11-18T20:16:06Z Sourisdudesert 1 wikitext text/x-wiki == About "cheating" == In the "real life Hanabi", you can talk. That's why we choosed to let the chat open for the online version. As a consequence, this is very easy to cheat at Hanabi. And as you can imagine, this is very stupid and this has no interest... except for ELO boosting. This is the reason why for this game there is no international ranking (ie: best player, second best player) and no trophies associated to it. == ELO rating == If you are playing with ELO rating on, your ELO may be changed at the end of the game. Here is how it works: 1) Every player on the team is temporarily considered as having the average ELO rating of the team. 2) The system will generate a bot associated with the score your team has achieved (let’s call it '''Hanabot'''). Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolor), the number of players on the team and, most importantly, your team's score. All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players. 3) Your team (actually your team's average ELO) will now compete against Hanabot. The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot. If your score is below 18 (50-card game) or below 21 (60-card game), your team is considered as losing against the weakest Hanabot for this configuration (variant and number of players). FYI, you can find all bots' ELO ratings here: (available soon) The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills. A loss (3 Strike tokens) is the same as a score of 0. If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points. 02296e8f65f0ad8c73b30043b060c7d4982eebc6 1290 1289 2014-11-18T22:29:26Z Runtly 6144 wikitext text/x-wiki == Cards == In a standard game of Hanabi, there are 5 colors of cards of rank 1 through 5. In each suit there are -three 1s -two 2s -two 3s -two 4s -one 5 == About "cheating" == In the "real life Hanabi", you can talk. That's why we chose to let the chat open for the online version. As a consequence, this is very easy to cheat at Hanabi. And as you can imagine, this is very stupid and this has no interest... except for ELO boosting. This is the reason why for this game there is no international ranking (ie: best player, second best player) and no trophies associated to it. == ELO rating == If you are playing with ELO rating on, your ELO may be changed at the end of the game. Here is how it works: 1) Every player on the team is temporarily considered as having the average ELO rating of the team. 2) The system will generate a bot associated with the score your team has achieved (let’s call it '''Hanabot'''). Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolor), the number of players on the team and, most importantly, your team's score. All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players. 3) Your team (actually your team's average ELO) will now compete against Hanabot. The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot. If your score is below 18 (50-card game) or below 21 (60-card game), your team is considered as losing against the weakest Hanabot for this configuration (variant and number of players). FYI, you can find all bots' ELO ratings here: (available soon) The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills. A loss (3 Strike tokens) is the same as a score of 0. If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points. b2efdfd324e574a1095854c099196141062c7619 1291 1290 2014-11-18T22:30:00Z Runtly 6144 /* Cards */ wikitext text/x-wiki == Cards == In a standard game of Hanabi, there are 5 colors of cards of rank 1 through 5. In each suit there are -three 1s -two 2s -two 3s -two 4s -one 5 == About "cheating" == In the "real life Hanabi", you can talk. That's why we chose to let the chat open for the online version. As a consequence, this is very easy to cheat at Hanabi. And as you can imagine, this is very stupid and this has no interest... except for ELO boosting. This is the reason why for this game there is no international ranking (ie: best player, second best player) and no trophies associated to it. == ELO rating == If you are playing with ELO rating on, your ELO may be changed at the end of the game. Here is how it works: 1) Every player on the team is temporarily considered as having the average ELO rating of the team. 2) The system will generate a bot associated with the score your team has achieved (let’s call it '''Hanabot'''). Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolor), the number of players on the team and, most importantly, your team's score. All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players. 3) Your team (actually your team's average ELO) will now compete against Hanabot. The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot. If your score is below 18 (50-card game) or below 21 (60-card game), your team is considered as losing against the weakest Hanabot for this configuration (variant and number of players). FYI, you can find all bots' ELO ratings here: (available soon) The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills. A loss (3 Strike tokens) is the same as a score of 0. If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points. ed83097c1959cb7a9559db5d0adb36b0dea52fa6 1292 1291 2014-11-18T22:47:35Z Beri 6819 /* Cards */ wikitext text/x-wiki == Cards == In a standard game of Hanabi, there are 5 colors of cards of value 1 to 5. In each suit there are -three 1s -two 2s -two 3s -two 4s -one 5 == About "cheating" == In the "real life Hanabi", you can talk. That's why we chose to let the chat open for the online version. As a consequence, this is very easy to cheat at Hanabi. And as you can imagine, this is very stupid and this has no interest... except for ELO boosting. This is the reason why for this game there is no international ranking (ie: best player, second best player) and no trophies associated to it. == ELO rating == If you are playing with ELO rating on, your ELO may be changed at the end of the game. Here is how it works: 1) Every player on the team is temporarily considered as having the average ELO rating of the team. 2) The system will generate a bot associated with the score your team has achieved (let’s call it '''Hanabot'''). Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolor), the number of players on the team and, most importantly, your team's score. All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players. 3) Your team (actually your team's average ELO) will now compete against Hanabot. The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot. If your score is below 18 (50-card game) or below 21 (60-card game), your team is considered as losing against the weakest Hanabot for this configuration (variant and number of players). FYI, you can find all bots' ELO ratings here: (available soon) The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills. A loss (3 Strike tokens) is the same as a score of 0. If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points. f339826239f67337da130c7be512775a9fed7de3 1293 1292 2014-11-18T22:48:39Z Beri 6819 /* About "cheating" */ wikitext text/x-wiki == Cards == In a standard game of Hanabi, there are 5 colors of cards of value 1 to 5. In each suit there are -three 1s -two 2s -two 3s -two 4s -one 5 == About "cheating" == In the "real life Hanabi", you can talk. That's why we chose to let the chat open for the online version. As a consequence, it is very easy to cheat at Hanabi. However, as you can imagine, cheating is very stupid and has no interest... except for ELO boosting. This is why there is no international ranking for this game (ie: best player, second best player) and no trophies associated to it. == ELO rating == If you are playing with ELO rating on, your ELO may be changed at the end of the game. Here is how it works: 1) Every player on the team is temporarily considered as having the average ELO rating of the team. 2) The system will generate a bot associated with the score your team has achieved (let’s call it '''Hanabot'''). Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolor), the number of players on the team and, most importantly, your team's score. All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players. 3) Your team (actually your team's average ELO) will now compete against Hanabot. The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot. If your score is below 18 (50-card game) or below 21 (60-card game), your team is considered as losing against the weakest Hanabot for this configuration (variant and number of players). FYI, you can find all bots' ELO ratings here: (available soon) The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills. A loss (3 Strike tokens) is the same as a score of 0. If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points. f95465141cf2483ccf84dcc0de17542756243d3b 1295 1293 2014-11-20T15:27:04Z Beri 6819 /* ELO rating */ wikitext text/x-wiki == Cards == In a standard game of Hanabi, there are 5 colors of cards of value 1 to 5. In each suit there are -three 1s -two 2s -two 3s -two 4s -one 5 == About "cheating" == In the "real life Hanabi", you can talk. That's why we chose to let the chat open for the online version. As a consequence, it is very easy to cheat at Hanabi. However, as you can imagine, cheating is very stupid and has no interest... except for ELO boosting. This is why there is no international ranking for this game (ie: best player, second best player) and no trophies associated to it. == ELO rating == If you are playing with ELO rating on, your ELO may be changed at the end of the game. Here is how it works: 1) Every player on the team is temporarily considered as having the average ELO rating of the team. 2) The system will generate a bot associated with the score your team has achieved (let’s call it '''Hanabot'''). Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolor), the number of players on the team and, most importantly, your team's score. All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players. 3) Your team (actually your team's average ELO) will now compete against Hanabot. The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot. If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000. FYI, you can find all bots' ELO ratings here: (available soon) The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills. A loss (3 Strike tokens) is the same as a score of 0. If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points. 6f0de10de3d110f2c53891a3ad06d863f801be91 1296 1295 2014-11-20T16:02:52Z Beri 6819 /* ELO rating */ wikitext text/x-wiki == Cards == In a standard game of Hanabi, there are 5 colors of cards of value 1 to 5. In each suit there are -three 1s -two 2s -two 3s -two 4s -one 5 == About "cheating" == In the "real life Hanabi", you can talk. That's why we chose to let the chat open for the online version. As a consequence, it is very easy to cheat at Hanabi. However, as you can imagine, cheating is very stupid and has no interest... except for ELO boosting. This is why there is no international ranking for this game (ie: best player, second best player) and no trophies associated to it. == ELO rating == If you are playing with ELO rating on, your ELO may be changed at the end of the game. Here is how it works: 1) Every player on the team is temporarily considered as having the average ELO rating of the team. 2) The system will generate a bot associated with the score your team has achieved (let’s call it '''Hanabot'''). Hanabot’s ELO rating depends on the variant you are playing (50 cards, 60 cards, 60 cards multicolor), the number of players on the team and, most importantly, your team's score. All Hanabot’s ELO ratings have been set by an experienced player, they are not random or simply proportional to the score/number of players. 3) Your team (actually your team's average ELO) will now compete against Hanabot. The system will calculate your team’s ELO gain/loss as though your team had tied with Hanabot. If your score is below 18 (50-card game) or below 21 (60-card game), Hanabot's ELO is always 1000. FYI, you can find all bots' ELO ratings here: http://forum.boardgamearena.com/viewtopic.php?f=3&t=4814 The 55-card variant (50 cards + 1 of each value in the sixth color) cannot be played with ELO rating on. This is because this variant is highly dependent on draw and a team’s score may not always reflect the players’ skills. A loss (3 Strike tokens) is the same as a score of 0. If you achieve the perfect score and this should cost you ELO points, you will be considered as having beaten the bot associated with the score, so that you lose no ELO points. 2c214cc73b3555b2be166d17d957afd5a446b4af Kaozeal:Reputation 1 176 1294 2014-11-19T19:25:44Z Mechler 6923 Created page with "I don't understand how to thank someone after my first game and I'm having trouble finding information about how that works." wikitext text/x-wiki I don't understand how to thank someone after my first game and I'm having trouble finding information about how that works. 3225f58d41c86ecc70bcec1be1932cd6e186320b Studio file reference 0 54 1297 945 2014-11-20T20:36:01Z Denis 6788 /* .game.php */ wikitext text/x-wiki This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment. === 'img' directory === This directory contains the images for your game (the game art). === gameinfos.inc.php === In this file you describe the meta-information for your game: game name, publisher name, number of player, game categories, etc... === dbmodel.sql === File for creating specific database tables that you will need to persist data during the game (for example a table for cards). === gameoptions.inc.php === File for describing your game options (= game variants) === <gamename>.action.php === File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions. === <gamename>.css === CSS styles specific to your game. === <gamename>.game.php === This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. Also see [[Main_game_logic:_yourgamename.game.php]]. === <gamename>.js === This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. === <gamename>.view.php and <gamename>_<gamename>.tpl === Files used to set up the page layout ('view') for the game. === material.inc.php === File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants. === states.inc.php === This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). === stats.inc.php === File used to list statistics that you want to update during the game to be presented to players at the end of the game. 1bfd40945f627538750988f56f62ac3907223354 1298 1297 2014-11-20T20:36:33Z Denis 6788 /* .game.php */ wikitext text/x-wiki This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment. === 'img' directory === This directory contains the images for your game (the game art). === gameinfos.inc.php === In this file you describe the meta-information for your game: game name, publisher name, number of player, game categories, etc... === dbmodel.sql === File for creating specific database tables that you will need to persist data during the game (for example a table for cards). === gameoptions.inc.php === File for describing your game options (= game variants) === <gamename>.action.php === File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions. === <gamename>.css === CSS styles specific to your game. === <gamename>.game.php === This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. Also see [[Main_game_logic:_yourgamename.game.php|game.php]]. === <gamename>.js === This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. === <gamename>.view.php and <gamename>_<gamename>.tpl === Files used to set up the page layout ('view') for the game. === material.inc.php === File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants. === states.inc.php === This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). === stats.inc.php === File used to list statistics that you want to update during the game to be presented to players at the end of the game. c4e1209d17ec4232b6016c1708292573105b2fbc 1299 1298 2014-11-20T20:37:54Z Denis 6788 /* stats.inc.php */ wikitext text/x-wiki This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment. === 'img' directory === This directory contains the images for your game (the game art). === gameinfos.inc.php === In this file you describe the meta-information for your game: game name, publisher name, number of player, game categories, etc... === dbmodel.sql === File for creating specific database tables that you will need to persist data during the game (for example a table for cards). === gameoptions.inc.php === File for describing your game options (= game variants) === <gamename>.action.php === File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions. === <gamename>.css === CSS styles specific to your game. === <gamename>.game.php === This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. Also see [[Main_game_logic:_yourgamename.game.php|game.php]]. === <gamename>.js === This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. === <gamename>.view.php and <gamename>_<gamename>.tpl === Files used to set up the page layout ('view') for the game. === material.inc.php === File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants. === states.inc.php === This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). === stats.inc.php === File used to list statistics that you want to update during the game to be presented to players at the end of the game. === version.php === Don't edit this file. It is used internally by the build system. 48d4bc1e117741507a211fbb1f051fb6d9ebdbaa Practical debugging 0 100 1300 829 2014-11-20T20:40:25Z Denis 6788 /* Debugging my game when it cannot start */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" as per [[Studio logs]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> === Add traces to your code === You can use the following functions in your game to add server side logging: '''self::debug( $message );''' // debug level logging '''self::trace( $message );''' // info level logging '''self::warn( $message );''' // warning level logging '''self::error( $message );''' // error level logging To see the logs, you should check the "Current table error log" in the [[Studio_back-office|Studio backoffice]]. This can be useful when you need to follow the flow of your code and not just stop it to see how it goes at some point. Only the error log level will appear in production. This level should be used only for critical problems. Other levels will show only in the development environment and can be used as you see fit. == Debugging my HTML/CSS layout == Situation examples: * why my game element doesn't show up in the interface? * why my CSS property hasn't been applied to this element? * why this game element is displayed at this position? A first useful tip when an element does not show up in the interface is to give it a red background: <pre> #my_element { ... some CSS definitions ... background-color: red; } </pre> This way, you know if the element is not visible because of some of its CSS property or because of anything else. Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property. Using Chrome "Elements" tab (thre first one), you can: * See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code. * Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles. * You can even modify directly some CSS property and see if how it looks immediately on the game interface. == Debugging my Javascript game interface logic == Compare to PHP debugging, Javascript debugging can sometimes be painful. Here's are some tips to make your life easier while developing and debugging Javascript: === Do complex things on PHP side === PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first. The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property. Note: check Reversi example for this. === Add traces in your code === You can use the following: '''console.log( variable_to_inspect )''' It will give you the object structure of the variable in the Javascript console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. '''alert( variable_to_inspect )''' It will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. == Some frequent errors == === when launching the game "Fatal error during creation of database ebd_quoridor_389 Not logged." === Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an "args" function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. === when refreshing the web page, the interface remains on "Application loading..." === In this case, you probably have a syntax error in your Javascript code, and the interface refuses to load. To find this error, check if there is an error message in the Javascript console (F12). If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition. === When I do a move, I got "Move recorded, waiting for update ..." forever === "Move recorded" means that your ajaxcall request has been sent to the server and returned normally. "Waiting for update" means that your client interface is waiting for some notifications from the server that correspond to the move we just did. If this message stays forever, it is probably that your PHP code does not send any notification when the move happens, which is abnormal. To fix this: add a notifyAllPlayers or a notifyPlayer call in your PHP code. === Some player action is triggered randomly when I click somewhere on the game area === You probably used "dojo.connect" on a null object. In this case, dojo.connect associate the event (ex: "onclick") to the whole game area. Most of the time it happens in this situation, when my_object element does not exists: <pre> dojo.connect( $("my_object"), "onclick", this, function() { ... } </pre> To determine if this is the case, place "alert( $("my_object") )" before the dojo.connect to check if the object exists or not. === Javascript does not know how to sum two numbers === Be careful when you manipulate integers returned by notifications: most of the time, Javascript considers they are Strings and not Integers. As a result: <pre> var i=1; i += notif.args.increment; // With notif.args.increment='1' alert( i ); // i=11 instead of 2 !! Javascript concatenate 2 strings ! </pre> To solve this, you should use the "toint" function: <pre> var i=1; i += toint( notif.args.increment ); // With notif.args.increment='1' alert( i ); // i=2 :) </pre> === Javascript: do not use substr with negative numbers === To get the last characters of a string, use "slice" instead of "substr" which has a bug on IE: <pre> var three_last_characters = string.substr( -3 ); // Wrong var three_last_characters = string.slice( -3 ); // Correct </pre> c7a42aea6fea74da42a5e92539d3821e8ec77b8d Gamehelpmachiavelli 0 133 1301 991 2014-12-02T12:53:49Z Nimoya 7196 /* How to play */ wikitext text/x-wiki == Game materials == Machiavelli is played with 2 or more french decks without using jokers. == Goal of the game == The game ends when a player plays all his cards or when the deck is depleted. == Game setup == Every player get 15 cards. Cards are secret and visible by its owner only. Put the rest of the deck on the table. == How to play == Each turn players can do a sequence of action, until the turn ends. Actions: * ''Draw a card'' The player can draw a card from the deck and his turn ends. * ''Play cards'' Player can play cards from his hand, laying them on the table and respecting the following rules: 1) Cards on the table must always form groups that contain at least 3 cards. 2) Groups on the table must be sets or runs. - Sets are groups of 3 or 4 cards of the same value (e.g. Q♥, Q♦, Q♣). - Runs are groups of cards of the same suit whose values are in sequence (e.g. 8♥,9♥,10♥,J♥,Q♥). The card rank start from ace to king: A, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K. Cards can be played also melding them to an existing group on the table as long as the previous rules are respected (e.g. player decides to meld 3♣, 7♣, 8♣ to an existing run on the table, made by 4♣, 5♣, 6♣ of clubs. He can meld the cards in the right sequence). * ''Take cards'' Player can take one or more groups of cards from the table adding them to his hand. Before his turn ends, he must play all cards he took from the table. Player may play these cards creating new groups, different from the previous ones, and using cards he already had in hand too. Example: Groups on the table: 3♣, 4♣, 5♣, 6♣ / Q♥, Q♦, Q♠ Player's hand: 5♣, 7♣, 8♣, Q♣, J♥, K♥ Player takes the 2 groups on the table, then he plays cards creating these new groups: 3♣, 4♣, 5♣ / 5♣, 6♣, 7♣, 8♣ / J♥, Q♥, K♥ / Q♦, Q♠, Q♣ * ''Restore'' If a player took cards from the table and he is no more able to play all taken cards, he may force his turn ends by restoring the original game situation on the table and of his hand. He must put back the taken cards on the table, restoring the original groups and collecting cards he had in his hand that he may have played. Once restored, player must draw 1 cards from the deck and pass. In case player is not able to restore, the other players will help him to do it and then he must draw 3 cards as penalty. NOTE WELL: In the BGA version cards taken from the table are tagged with a red sign as reminder to play it before passing. '''The ''Restore'' action can be automatically performed clicking on a specific button and player receive 1 card from the deck'''. 3 cards penalty is not considered. * ''Pass'' Player can pass only if he played cards and if he has no cards taken from the table in his hand. == End of the game == Game ends as soon as a player has no more cards in his hand or the deck is depleted. In the second case, the winner is the player with less cards in his hand. 2dd80ffba8c4ac23b07389a2270f2897d2273161 Gamehelptokaido 0 134 1302 1282 2014-12-05T03:23:34Z Jgbaxter 6455 cleaned up game options. wikitext text/x-wiki ==  Objective of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' ===Encounters=== :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - Pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object and 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. ===Farm=== :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X= Loses coins, 1= Recovers coins, 2/3/3/4= Gains double that many coins). ===Hot Springs=== :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4 points (counts for ''Bather'' accomplishment). ===Panorama=== :('''B''') There are three Panorama types and are made of 3 (Field), 4 (Mountain), or 5 (Paddy) sections. : When a player stops on a Panorama they take the first Panorama of that type that they do not have (value from 1-5) and scores that many points. Each traveler can create only a single panorama of each type and when completed can no longer stop on the spaces corresponding to that type. :('''E''') A player may instead take a Cherry Tree and gain 2 points and 1 coin. ===Temple=== :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn points. ===Village=== :('''B''') The player draws 3 Souvenir cards and can purchase 1-3 of these cards for 1-3 coins. There are four different Souvenirs and are grouped in sets. The first Souvenir in each set is worth 1 point, the next is 3 points, then 5 and 7 points. :('''E''') Acquire a Legendary Object (counts for ''Collector'' accomplishment) for 1-3 coins: :* Shodo & Emaki - For 1 coin, gain 1 point for each Souvenir or Legendary Object. Gain 1 point for each Souvenir thereafter. :* Buppatsu & Ema - For 2 coins this counts as a different Souvenir type, 5 types in a set is worth 9 points. :* Murasame & Masamune - For 3 coins, gain 8 points. ===Inns=== : All Travelers must stop at each Inn, they may not leave until all players have arrived at that Inn. : The Inns allow players to buy one unique Meal card for 1-3 coins that are worth 6 points. : When the first traveler arrives at an Inn, they draw as many Meal cards as there are players, plus 1. : As players arrive at the Inn they may buy a Meal card to add to their collection, hidden from other players. :* ''A traveler cannot taste the same culinary specialty twice during their journey.'' :* ''A traveler can never purchase more than one Meal card per Inn.'' :* ''A traveler is never obliged to purchase a Meal card.'' == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. == Game Options == === Initiation === A simplified version with no Travelers and everyone starting with 7 coins. === Return Trip === Instead of starting on the left side of the board, players move right to left. === Gastronomy === The first person arriving at an Inn draws one less card, only drawing one card per player. === Preparations === When leaving the starting Inn, the last player gains two coins, the next gains one coin, the fourth and fifth players each lose a coin. === Crossroads === This expansion adds a second option at each location (other than the Inns) to choose from when stopping. === New Encounters === This adds 4 new encounters to the possibilities when on the 'Encounters' space. c6cd31cca48e274957144f330d4d4cea7c0cb2c5 1303 1302 2014-12-07T02:56:29Z Jgbaxter 6455 added cherry tree card number wikitext text/x-wiki ==  Objective of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' ===Encounters=== :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - Pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object and 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. ===Farm=== :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X= Loses coins, 1= Recovers coins, 2/3/3/4= Gains double that many coins). ===Hot Springs=== :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4 points (counts for ''Bather'' accomplishment). ===Panorama=== :('''B''') There are three Panorama types and are made of 3 (Field), 4 (Mountain), or 5 (Paddy) sections. : When a player stops on a Panorama they take the first Panorama of that type that they do not have (value from 1-5) and scores that many points. Each traveler can create only a single panorama of each type and when completed can no longer stop on the spaces corresponding to that type. :('''E''') A player may instead take a Cherry Tree and gain 2 points and 1 coin. (''There are 6 Cherry Tree cards.'') ===Temple=== :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn points. ===Village=== :('''B''') The player draws 3 Souvenir cards and can purchase 1-3 of these cards for 1-3 coins. There are four different Souvenirs and are grouped in sets. The first Souvenir in each set is worth 1 point, the next is 3 points, then 5 and 7 points. :('''E''') Acquire a Legendary Object (counts for ''Collector'' accomplishment) for 1-3 coins: :* Shodo & Emaki - For 1 coin, gain 1 point for each Souvenir or Legendary Object. Gain 1 point for each Souvenir thereafter. :* Buppatsu & Ema - For 2 coins this counts as a different Souvenir type, 5 types in a set is worth 9 points. :* Murasame & Masamune - For 3 coins, gain 8 points. ===Inns=== : All Travelers must stop at each Inn, they may not leave until all players have arrived at that Inn. : The Inns allow players to buy one unique Meal card for 1-3 coins that are worth 6 points. : When the first traveler arrives at an Inn, they draw as many Meal cards as there are players, plus 1. : As players arrive at the Inn they may buy a Meal card to add to their collection, hidden from other players. :* ''A traveler cannot taste the same culinary specialty twice during their journey.'' :* ''A traveler can never purchase more than one Meal card per Inn.'' :* ''A traveler is never obliged to purchase a Meal card.'' == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. == Game Options == === Initiation === A simplified version with no Travelers and everyone starting with 7 coins. === Return Trip === Instead of starting on the left side of the board, players move right to left. === Gastronomy === The first person arriving at an Inn draws one less card, only drawing one card per player. === Preparations === When leaving the starting Inn, the last player gains two coins, the next gains one coin, the fourth and fifth players each lose a coin. === Crossroads === This expansion adds a second option at each location (other than the Inns) to choose from when stopping. === New Encounters === This adds 4 new encounters to the possibilities when on the 'Encounters' space. eead6e66a9a192f363e543c7cbafa093a1d87599 Gamehelptzolkin 0 129 1304 1098 2014-12-16T18:40:55Z Squarerootofthree 5668 /* Player turn */ wikitext text/x-wiki Rules are here: http://czechgames.com/files/Tzolkin_EN.pdf == '''For Each Round''' == - Each player takes their turn, going around the table - On a food day, feed your workers and take your rewards - Advance the Calendar == '''Player turn''' == - '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple) - '''Either place workers OR pick up workers''' -- ''Placing workers'': pay for the number of workers you place. The cost for the number of workers you place is 0, 1, 3, 6, 10, or 15 for, respectively, 1, 2, 3, 4, 5, or 6 workers placed on that turn, plus the cumulative cost noted next to each of your placed workers. -- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either --- Use the action where your worker was standing --- Use a lower action on the wheel from where your worker was standing(if not standing on a free action space,pay 1 corn for each step back) --- Do nothing. == '''Food Day''' == -'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for. -- For each worker not fed, you lose 3 points -'''Take Rewards''' --''Middle of Age (Brown days)'' --- Receive items shown on the left edge of temples from step you are on and all steps below -- ''End of Age (Teal Days)'' --- Remove all Age 1 buildings and fill spaces with Age 2 buildings/ --- Receive points shown on the right edge of temples for the step you are on. --- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus. == '''Advance the Calendar''' == If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day. Otherwise: - The worker on the Starting Player space returns to the player -- If this person was not the starting player, they take the starting player marker. -- If they were the starting player, the starting player marker is moved to the player on his left - Advance the Tzolk'in Gear one day. - The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears. -- If you use this option, flip your board to dark side up. -- This does not avoid food days. b800d5739c93fdd2ac6a8daa5f4f4da5b5dbd9e9 1305 1304 2014-12-16T18:44:48Z Squarerootofthree 5668 /* Player turn */ wikitext text/x-wiki Rules are here: http://czechgames.com/files/Tzolkin_EN.pdf == '''For Each Round''' == - Each player takes their turn, going around the table - On a food day, feed your workers and take your rewards - Advance the Calendar == '''Player turn''' == - '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple) - '''Either place workers OR pick up workers''' -- ''Placing workers'': pay corn for the number of workers you place. The cost for the number of workers you place is 0, 1, 3, 6, 10, or 15 for, respectively, 1, 2, 3, 4, 5, or 6 workers placed on that turn, plus the cumulative cost noted next to each of your placed workers. -- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either --- Use the action where your worker was standing --- Use a lower action on the wheel from where your worker was standing(if not standing on a free action space,pay 1 corn for each step back) --- Do nothing. == '''Food Day''' == -'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for. -- For each worker not fed, you lose 3 points -'''Take Rewards''' --''Middle of Age (Brown days)'' --- Receive items shown on the left edge of temples from step you are on and all steps below -- ''End of Age (Teal Days)'' --- Remove all Age 1 buildings and fill spaces with Age 2 buildings/ --- Receive points shown on the right edge of temples for the step you are on. --- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus. == '''Advance the Calendar''' == If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day. Otherwise: - The worker on the Starting Player space returns to the player -- If this person was not the starting player, they take the starting player marker. -- If they were the starting player, the starting player marker is moved to the player on his left - Advance the Tzolk'in Gear one day. - The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears. -- If you use this option, flip your board to dark side up. -- This does not avoid food days. d74e6ac8e0eed40a9738f40b51cb0eb477082985 1306 1305 2014-12-16T19:04:48Z Squarerootofthree 5668 /* Food Day */ wikitext text/x-wiki Rules are here: http://czechgames.com/files/Tzolkin_EN.pdf == '''For Each Round''' == - Each player takes their turn, going around the table - On a food day, feed your workers and take your rewards - Advance the Calendar == '''Player turn''' == - '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple) - '''Either place workers OR pick up workers''' -- ''Placing workers'': pay corn for the number of workers you place. The cost for the number of workers you place is 0, 1, 3, 6, 10, or 15 for, respectively, 1, 2, 3, 4, 5, or 6 workers placed on that turn, plus the cumulative cost noted next to each of your placed workers. -- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either --- Use the action where your worker was standing --- Use a lower action on the wheel from where your worker was standing(if not standing on a free action space,pay 1 corn for each step back) --- Do nothing. == '''Food Day''' == -'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for. -- For each worker not fed, you lose 3 points -'''Take Rewards''' --''Middle of Age (Brown days)'' --- Receive items shown on the left edge of temples from step you are on and all steps below -- ''End of Age (Teal Days)'' --- Remove all Age 1 buildings and fill spaces with Age 2 buildings --- Receive points shown on the right edge of temples for the step you are on. --- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus. == '''Advance the Calendar''' == If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day. Otherwise: - The worker on the Starting Player space returns to the player -- If this person was not the starting player, they take the starting player marker. -- If they were the starting player, the starting player marker is moved to the player on his left - Advance the Tzolk'in Gear one day. - The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears. -- If you use this option, flip your board to dark side up. -- This does not avoid food days. 539c2525729420bfd7921bbc58ea9857256c2977 Gamehelpinjawara 0 173 1307 1275 2014-12-23T17:06:46Z Lyliadoudou 7463 /* 2. TRY TO SOLVE A CHALLENGE (if it's possible) */ wikitext text/x-wiki == AIM OF THE GAME == The aim of the INJAWARA board game is to work in team cooperatively and contribute to solve at least 1 Challenge related to each Millennium Development Goal and 1 for each Region by moving the needed resources through the six regions and reply to questions related to the Challenges faced. The longer you ignore a problem, the more it will get worse! If a problem becomes too serious it will become impossible to solve it, and you will lose all. == THE GAME == The INJAWARA board game has no player turns, but in each round, all players, as a team, must decide the actions to do. How decisions are taken must be agreed by all players at the beginning of the game. Every round has three phases: === 1. USE OR MOVE RESOURCES (Optional) === Optionally, the team may make one of the following actions: move a resource to an adjacent region, use one unlocked resource power or simply do nothing in this phase. ==== A. MOVE A RESOURCE TO AN ADJACENT REGION ==== All regions are linked between them, indicated by the black arrows on the board. You can move one resource from one region to another linked region. ==== B. USE AN UNLOCKED RESOURCE POWER ==== If a resource has its power unlocked, you can use its power. Please note that after using the power of a resource you have to lock its power again and turn that resource upside down. All powers are the following: ===== Economic resources ===== Swap places of two resources on the board. Economic resources may be moved in this way as well. ===== Professionals ===== Move a resource to any region on the board. Professionals may be moved in this way as well. ===== Materials ===== Move towards higher score one box the score token of one of the following MDGS: 1, 2, 6, 7. ===== Politics ===== Move towards higher score one box the score token of one of the following MDGS: 3, 4, 5, 8. ===== Justice ===== You can discard a challenge token placed in any region, but it's not treated as solved. ===== Education ===== This is the only resource you have to use after having answered to the question. You can answer another questions, after failing a previous one, in order to solve a challenge. ==== C. DO NOTHING ==== Whilst there is a challenge which may be solved (see 2. Try to solve a challenge), we can skip this first phase and go straight for the challenge. In the same manner, althought there was not a challenge which may be solved, it's possible for the team to pass in this phase and go just right to 3. A NEW CHALLENGE APPEARS. This is an actual valid option, but encourage the team to use it carefully. Maybe you can earn some more points by moving a resource or using a power, instead of letting the turn move on. === 2. TRY TO SOLVE A CHALLENGE (if it's possible) === Every challenge token has three data items: The region where it appears, the MDG affected by it, and the needed resource to solve it. If in the moment to start the turn or after using or moving resources, the convenient resource is on the same region than a challenge which needs it, the team may try to solve the challenge (see illustration). There is only one constraint: If you chose to move a resource at the beginning of the turn, you may only try to solve the challenges associated to that resource. This doesn't apply after using a power or if you decide not to move nor use a resource. If there is more than one challenge you can solve, YOU CANNOT SOLVE BOTH, but you have to choose which one you want to solve. So, grab the first question card from the question deck, and read out loud the question related to the MDG indicated by the challenge, and try to answer it working as a team. The right answers are in the reverse of the card, so try not to lift it up as others may see the answer. If you answer correctly, move forward the score marker associated to the MDG indicated by the challenge three boxes towards a higher score. It's not possible to move an score token beyond 100 points. If the score marker shows an X, turn it upside down to see the green tick. In the same manner, turn the region marker, where the challenge is located, upside down, if it wasn't showing the green tick yet. Likewise, if the resource was 'locked', turn it upside down, in order to unlock its power. The challenge token is discarded and place it in the discarded pile, marked with an X on the board. If you answer incorrectly, don't move any marker or token. In both cases, leave the question card on the discard pile, marked with an X, next to que question mark on the board. Place it with the questions facing up. === 3. A NEW CHALLENGE APPEARS === The challenge we left in the space marked by an eye on the board, is the next challenge that will appear in the game. Grab that challenge and place it on the region indicated by the leaf shape. In that moment, if in that region there was any other unsolved challenges, move one box towards a lower score, on the score board, all MDGs markers present in this region's challenges, without counting on th new challenge. ==== '-1' TOKEN ==== If the next challenge token is a'-1' one, check all unsolved challenges on the board and move one box towards a lower score, on the score board, all MDGs markeres present. Only one box may be moved per MDG, so ignore other challenges that references the same MDG. In that moment, grab all tokens from discarded challenges pile (marked with an X on the board) and the '-1' token and put them back into the bag. Grab a new challenge token from the bag, randomly, and place it on the space marked with an eye. Now you know which is the challenge for the next round. == END OF THE GAME == There are two possible scenarios when the game ends: 1. ''The team loses the game'', if in any moment of the game, any MDG score marker reaches the skull. If you want to calculate your final score, see the "Scoring. If we lose." section below. 2. ''The team wins the game'', if in any moment of the game, all MDG score markers show the green tick and all region markers show the green tick as well. If this situation occurs in the middle of several challenges solving, you can end solving up all of them (and also use the Education power, if this is unlocked). == SCORING == === If we lose === If our team has lost the game, move towards a lower score, all MDG markers, 3 boxes. If any of the markers reaches the skull, it cannot be moved beyond. Then, sum up all the scores, knowing the skull scores 0 points. === If we won === Sum up all scores of all MDGs markers and this will be your final score. (On the score board you can see an aid for suming up to three markers on the same score box, on grey). b25f8df9391ce36e45fa6053c51905efbac946df 1308 1307 2014-12-23T17:31:17Z Lyliadoudou 7463 /* '-1' TOKEN */ wikitext text/x-wiki == AIM OF THE GAME == The aim of the INJAWARA board game is to work in team cooperatively and contribute to solve at least 1 Challenge related to each Millennium Development Goal and 1 for each Region by moving the needed resources through the six regions and reply to questions related to the Challenges faced. The longer you ignore a problem, the more it will get worse! If a problem becomes too serious it will become impossible to solve it, and you will lose all. == THE GAME == The INJAWARA board game has no player turns, but in each round, all players, as a team, must decide the actions to do. How decisions are taken must be agreed by all players at the beginning of the game. Every round has three phases: === 1. USE OR MOVE RESOURCES (Optional) === Optionally, the team may make one of the following actions: move a resource to an adjacent region, use one unlocked resource power or simply do nothing in this phase. ==== A. MOVE A RESOURCE TO AN ADJACENT REGION ==== All regions are linked between them, indicated by the black arrows on the board. You can move one resource from one region to another linked region. ==== B. USE AN UNLOCKED RESOURCE POWER ==== If a resource has its power unlocked, you can use its power. Please note that after using the power of a resource you have to lock its power again and turn that resource upside down. All powers are the following: ===== Economic resources ===== Swap places of two resources on the board. Economic resources may be moved in this way as well. ===== Professionals ===== Move a resource to any region on the board. Professionals may be moved in this way as well. ===== Materials ===== Move towards higher score one box the score token of one of the following MDGS: 1, 2, 6, 7. ===== Politics ===== Move towards higher score one box the score token of one of the following MDGS: 3, 4, 5, 8. ===== Justice ===== You can discard a challenge token placed in any region, but it's not treated as solved. ===== Education ===== This is the only resource you have to use after having answered to the question. You can answer another questions, after failing a previous one, in order to solve a challenge. ==== C. DO NOTHING ==== Whilst there is a challenge which may be solved (see 2. Try to solve a challenge), we can skip this first phase and go straight for the challenge. In the same manner, althought there was not a challenge which may be solved, it's possible for the team to pass in this phase and go just right to 3. A NEW CHALLENGE APPEARS. This is an actual valid option, but encourage the team to use it carefully. Maybe you can earn some more points by moving a resource or using a power, instead of letting the turn move on. === 2. TRY TO SOLVE A CHALLENGE (if it's possible) === Every challenge token has three data items: The region where it appears, the MDG affected by it, and the needed resource to solve it. If in the moment to start the turn or after using or moving resources, the convenient resource is on the same region than a challenge which needs it, the team may try to solve the challenge (see illustration). There is only one constraint: If you chose to move a resource at the beginning of the turn, you may only try to solve the challenges associated to that resource. This doesn't apply after using a power or if you decide not to move nor use a resource. If there is more than one challenge you can solve, YOU CANNOT SOLVE BOTH, but you have to choose which one you want to solve. So, grab the first question card from the question deck, and read out loud the question related to the MDG indicated by the challenge, and try to answer it working as a team. The right answers are in the reverse of the card, so try not to lift it up as others may see the answer. If you answer correctly, move forward the score marker associated to the MDG indicated by the challenge three boxes towards a higher score. It's not possible to move an score token beyond 100 points. If the score marker shows an X, turn it upside down to see the green tick. In the same manner, turn the region marker, where the challenge is located, upside down, if it wasn't showing the green tick yet. Likewise, if the resource was 'locked', turn it upside down, in order to unlock its power. The challenge token is discarded and place it in the discarded pile, marked with an X on the board. If you answer incorrectly, don't move any marker or token. In both cases, leave the question card on the discard pile, marked with an X, next to que question mark on the board. Place it with the questions facing up. === 3. A NEW CHALLENGE APPEARS === The challenge we left in the space marked by an eye on the board, is the next challenge that will appear in the game. Grab that challenge and place it on the region indicated by the leaf shape. In that moment, if in that region there was any other unsolved challenges, move one box towards a lower score, on the score board, all MDGs markers present in this region's challenges, without counting on th new challenge. ==== '-1' TOKEN ==== If the next challenge token is a '-1' one, check all unsolved challenges on the board and move one box towards a lower score, on the score board, all MDGs markeres present. Only one box may be moved per MDG, so ignore other challenges that references the same MDG. In that moment, grab all tokens from discarded challenges pile (marked with an X on the board) and the '-1' token and put them back into the bag. Grab a new challenge token from the bag, randomly, and place it on the space marked with an eye. Now you know which is the challenge for the next round. == END OF THE GAME == There are two possible scenarios when the game ends: 1. ''The team loses the game'', if in any moment of the game, any MDG score marker reaches the skull. If you want to calculate your final score, see the "Scoring. If we lose." section below. 2. ''The team wins the game'', if in any moment of the game, all MDG score markers show the green tick and all region markers show the green tick as well. If this situation occurs in the middle of several challenges solving, you can end solving up all of them (and also use the Education power, if this is unlocked). == SCORING == === If we lose === If our team has lost the game, move towards a lower score, all MDG markers, 3 boxes. If any of the markers reaches the skull, it cannot be moved beyond. Then, sum up all the scores, knowing the skull scores 0 points. === If we won === Sum up all scores of all MDGs markers and this will be your final score. (On the score board you can see an aid for suming up to three markers on the same score box, on grey). a7309c51a0babc2700ef00b2384dd7de43dc79e1 Gamehelptashkalar 0 177 1309 2014-12-25T17:43:54Z Quinarbre 4507 Created page with "== Game forms == On Board Game Arena, Tash-Kalar may be played only by 2 players, and in 2 distinct forms : - '''The High Form''': Players score points for tasks and for leg..." wikitext text/x-wiki == Game forms == On Board Game Arena, Tash-Kalar may be played only by 2 players, and in 2 distinct forms : - '''The High Form''': Players score points for tasks and for legendary pieces currently on the board. - '''Deathmatch Duel''': No tasks. Players score points for destroying enemy pieces, for summoning legendary beings, and when their opponent invokes a flare. The actual board game also features Deathmatch Melee for 3 or 4 players, and team play. == Setup == Each player draws 6 cards : 3 beings from his or her own deck, 2 legends, and 1 flare. In '''High Form''', 3 tasks are revealed that may be claimed, along with a fourth "next task". In '''Deathmatch''', the player who plays second puts one common piece of each color on the game board, on marked squares. == Game play == Players take turns in clockwise order, beginning with the starting player. Each turn, you have 2 actions. Exception: The starting player has only 1 action on his or her first turn. Possible actions: - '''Place 1 common piece''' of your color on any empty square. If you have none left to place, you begin this action by picking up 1 of your common or heroic pieces, then place it as a common piece. - '''Summon a being'''. (See below.) - '''Discard 1 being''' that you drew from your deck. If you do, you may also return one or more of your other cards to the bottoms of their decks. Actions can be done in any order. You can do more than one “place” or “summon” action per turn (but no more than one “discard” action). You have to use all your actions. You can invoke a flare (see below) before or after any action. Invoking a flare does not cost you an action. Finish your turn by drawing cards so that you end up with 3 beings from your deck, 2 legends, and 1 flare. If you draw the last card in your deck, you may end up with fewer than 3. '''High Form''': At the end of the turn, you may claim exactly 1 of the current tasks, if you meet its criteria. '''Deathmatch''': At the end of your turn, score points for destroyed enemy pieces: 2 points for legendary, 1 point for heroic, 1 point for each pair of common pieces. You get no points for destroying your own pieces. You get no points for an un- paired common piece. Also score 1 point each time you summon a legend. (Upgrading a heroic piece does not count as “summoning a legend”.) == Summoning a being == To summon a being, use 1 action and do the following: - '''Play the card''' from your hand and choose a square on the board where your pieces match the pattern on the card. The pattern can be rotated (by 90, 180, or 270 degrees). Mirror images and flips also count as a match. The pieces used to summon the being can be the same rank as those depicted in the pattern or higher rank. Empty squares are not important to the pattern. - '''Place a piece of the indicated rank''' (upper left corner of the card) on the square indicated by the white-framed square in the pattern. This square may be empty, unless the pattern says it must be occupied by one of your pieces. If the square is occupied by a piece of the same rank or lower, destroy that piece when you put the new piece on the square. If the square is occupied by a piece of higher rank, you cannot summon the being. If all your pieces of that type are already on the board, you may still be able to summon the being by picking up a piece that is not required for the pattern and use it as the new piece. - Once the new piece is on the board, '''resolve the effect''' printed on the card. - After resolving the effect, discard the card. == Invoking a flare == You can invoke a flare on your turn before or after any action. To invoke a flare, you must meet at least one of the criteria: - You meet the upper criterion if your opponent has '''that many more upgraded pieces''' (heroic and legendary) on the board than you. - You meet the lower criterion if your opponent has '''that many more pieces (total)''' on the board than you. If you meet the upper criterion, you resolve the upper effect. If you meet the lower criterion, you resolve the lower effect. If you meet both, you resolve the upper effect first, then the lower. Once the card has been resolved, discard it. == Resolving effects of beings and flares == No other action can be taken and no flare can be invoked until the entire effect of the card is resolved. Some parts of an effect may be optional: - May indicates that a certain part of an effect is optional. - Up to always includes 0. Any parts that are not specified as optional are mandatory. If an effect cannot be performed fully, do the parts that can be done. When a card uses its own name, it is referring to the piece on the board that represents the summoned being. '''Keywords''': - Upgraded piece: a heroic or legendary piece. - Non-legendary piece: a common or heroic piece. - Piece: If a piece is not specified as belonging to you or an opponent, then the effect includes any player's piece. - Marked space: a colored space in the pattern. If the text does not refer to marked spaces, the colored spaces in the pattern are just illustrational. - Adjacent square: one of eight squares sharing an edge (orthogonally adjacent) or a corner (diagonally adjacent) with a given square. If the given square is not specified, assume it is the square currently occupied by the newly summoned piece. - Distance: the shortest number of moves required to get from one square to another. For example, adjacent squares are at distance 1. - Move: A move is always onto an adjacent square. A move onto an occupied square destroys the piece that was there. - Standard move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Combat move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Standard leap and combat leap: A leap is the same as a move, except the square doesn’t have to be adjacent. If not specified, a leap can be onto any square on the board. - Place: Like the “place” action. However, if there is no piece of the specified color and rank available, the piece cannot be placed. - Upgrade: Legendary pieces cannot be upgraded. To upgrade a common piece, flip it over. To upgrade a heroic piece, remove it and replace it with a legendary piece. If none is available, the heroic piece cannot be upgraded. - Downgrade: Common pieces cannot be downgraded. To downgrade a heroic piece, flip it over. To downgrade a legendary piece, replace it with a heroic piece. If none is available, the legendary piece cannot be downgraded. - Destroy: To destroy a piece, remove it from the board. - Convert: To convert an enemy piece, replace it with one of your pieces of the same rank (unless a different rank is specified). When keeping track of '''how many enemy pieces you destroyed''', count pieces you destroyed during summoning, pieces you destroyed with moves and leaps, pieces you destroyed with a “destroy” effect, and pieces you converted. Neither upgrading nor downgrading ever counts as destroying a piece. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. c5f4d3f15031046fd186c43fed16f26319f14ccf 1310 1309 2014-12-25T17:45:26Z Quinarbre 4507 wikitext text/x-wiki == Game forms == On Board Game Arena, Tash-Kalar may be played only by 2 players, and in 2 distinct forms : - '''The High Form''': Players score points for tasks and for legendary pieces currently on the board. - '''Deathmatch Duel''': No tasks. Players score points for destroying enemy pieces, for summoning legendary beings, and when their opponent invokes a flare. The actual board game also features Deathmatch Melee for 3 or 4 players, and team play. == Setup == Each player draws 6 cards : 3 beings from his or her own deck, 2 legends, and 1 flare. In '''High Form''', 3 tasks are revealed that may be claimed, along with a fourth "next task". In '''Deathmatch''', the player who plays second puts one common piece of each color on the game board, on marked squares. == Game play == Players take turns in clockwise order, beginning with the starting player. Each turn, you have 2 actions. Exception: The starting player has only 1 action on his or her first turn. Possible actions: - '''Place 1 common piece''' of your color on any empty square. If you have none left to place, you begin this action by picking up 1 of your common or heroic pieces, then place it as a common piece. - '''Summon a being'''. (See below.) - '''Discard 1 being''' that you drew from your deck. If you do, you may also return one or more of your other cards to the bottoms of their decks. Actions can be done in any order. You can do more than one “place” or “summon” action per turn (but no more than one “discard” action). You have to use all your actions. You can invoke a flare (see below) before or after any action. Invoking a flare does not cost you an action. Finish your turn by drawing cards so that you end up with 3 beings from your deck, 2 legends, and 1 flare. If you draw the last card in your deck, you may end up with fewer than 3. '''High Form''': At the end of the turn, you may claim exactly 1 of the current tasks, if you meet its criteria. '''Deathmatch''': At the end of your turn, score points for destroyed enemy pieces: 2 points for legendary, 1 point for heroic, 1 point for each pair of common pieces. You get no points for destroying your own pieces. You get no points for an un- paired common piece. Also score 1 point each time you summon a legend. (Upgrading a heroic piece does not count as “summoning a legend”.) == Summoning a being == To summon a being, use 1 action and do the following: - '''Play the card''' from your hand and choose a square on the board where your pieces match the pattern on the card. The pattern can be rotated (by 90, 180, or 270 degrees). Mirror images and flips also count as a match. The pieces used to summon the being can be the same rank as those depicted in the pattern or higher rank. Empty squares are not important to the pattern. - '''Place a piece of the indicated rank''' (upper left corner of the card) on the square indicated by the white-framed square in the pattern. This square may be empty, unless the pattern says it must be occupied by one of your pieces. If the square is occupied by a piece of the same rank or lower, destroy that piece when you put the new piece on the square. If the square is occupied by a piece of higher rank, you cannot summon the being. If all your pieces of that type are already on the board, you may still be able to summon the being by picking up a piece that is not required for the pattern and use it as the new piece. - Once the new piece is on the board, '''resolve the effect''' printed on the card. - After resolving the effect, discard the card. == Invoking a flare == You can invoke a flare on your turn before or after any action. To invoke a flare, you must meet at least one of the criteria: - You meet the upper criterion if your opponent has '''that many more upgraded pieces''' (heroic and legendary) on the board than you. - You meet the lower criterion if your opponent has '''that many more pieces (total)''' on the board than you. If you meet the upper criterion, you resolve the upper effect. If you meet the lower criterion, you resolve the lower effect. If you meet both, you resolve the upper effect first, then the lower. Once the card has been resolved, discard it. == Resolving effects of beings and flares == No other action can be taken and no flare can be invoked until the entire effect of the card is resolved. Some parts of an effect may be optional: - May indicates that a certain part of an effect is optional. - Up to always includes 0. Any parts that are not specified as optional are mandatory. If an effect cannot be performed fully, do the parts that can be done. When a card uses its own name, it is referring to the piece on the board that represents the summoned being. '''Keywords''': - Upgraded piece: a heroic or legendary piece. - Non-legendary piece: a common or heroic piece. - Piece: If a piece is not specified as belonging to you or an opponent, then the effect includes any player's piece. - Marked space: a colored space in the pattern. If the text does not refer to marked spaces, the colored spaces in the pattern are just illustrational. - Adjacent square: one of eight squares sharing an edge (orthogonally adjacent) or a corner (diagonally adjacent) with a given square. If the given square is not specified, assume it is the square currently occupied by the newly summoned piece. - Distance: the shortest number of moves required to get from one square to another. For example, adjacent squares are at distance 1. - Move: A move is always onto an adjacent square. A move onto an occupied square destroys the piece that was there. - Standard move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Combat move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Standard leap and combat leap: A leap is the same as a move, except the square doesn’t have to be adjacent. If not specified, a leap can be onto any square on the board. - Place: Like the “place” action. However, if there is no piece of the specified color and rank available, the piece cannot be placed. - Upgrade: Legendary pieces cannot be upgraded. To upgrade a common piece, flip it over. To upgrade a heroic piece, remove it and replace it with a legendary piece. If none is available, the heroic piece cannot be upgraded. - Downgrade: Common pieces cannot be downgraded. To downgrade a heroic piece, flip it over. To downgrade a legendary piece, replace it with a heroic piece. If none is available, the legendary piece cannot be downgraded. - Destroy: To destroy a piece, remove it from the board. - Convert: To convert an enemy piece, replace it with one of your pieces of the same rank (unless a different rank is specified). When keeping track of '''how many enemy pieces you destroyed''', count pieces you destroyed during summoning, pieces you destroyed with moves and leaps, pieces you destroyed with a “destroy” effect, and pieces you converted. Neither upgrading nor downgrading ever counts as destroying a piece. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. ---- These rules are extracted from CGE's full rules for Tash-Kalar. c98875127d6d1835b0b416d87169ddc1e0d693a9 1312 1310 2014-12-26T00:31:05Z Vikingj 6185 /* Resolving effects of beings and flares */ wikitext text/x-wiki == Game forms == On Board Game Arena, Tash-Kalar may be played only by 2 players, and in 2 distinct forms : - '''The High Form''': Players score points for tasks and for legendary pieces currently on the board. - '''Deathmatch Duel''': No tasks. Players score points for destroying enemy pieces, for summoning legendary beings, and when their opponent invokes a flare. The actual board game also features Deathmatch Melee for 3 or 4 players, and team play. == Setup == Each player draws 6 cards : 3 beings from his or her own deck, 2 legends, and 1 flare. In '''High Form''', 3 tasks are revealed that may be claimed, along with a fourth "next task". In '''Deathmatch''', the player who plays second puts one common piece of each color on the game board, on marked squares. == Game play == Players take turns in clockwise order, beginning with the starting player. Each turn, you have 2 actions. Exception: The starting player has only 1 action on his or her first turn. Possible actions: - '''Place 1 common piece''' of your color on any empty square. If you have none left to place, you begin this action by picking up 1 of your common or heroic pieces, then place it as a common piece. - '''Summon a being'''. (See below.) - '''Discard 1 being''' that you drew from your deck. If you do, you may also return one or more of your other cards to the bottoms of their decks. Actions can be done in any order. You can do more than one “place” or “summon” action per turn (but no more than one “discard” action). You have to use all your actions. You can invoke a flare (see below) before or after any action. Invoking a flare does not cost you an action. Finish your turn by drawing cards so that you end up with 3 beings from your deck, 2 legends, and 1 flare. If you draw the last card in your deck, you may end up with fewer than 3. '''High Form''': At the end of the turn, you may claim exactly 1 of the current tasks, if you meet its criteria. '''Deathmatch''': At the end of your turn, score points for destroyed enemy pieces: 2 points for legendary, 1 point for heroic, 1 point for each pair of common pieces. You get no points for destroying your own pieces. You get no points for an un- paired common piece. Also score 1 point each time you summon a legend. (Upgrading a heroic piece does not count as “summoning a legend”.) == Summoning a being == To summon a being, use 1 action and do the following: - '''Play the card''' from your hand and choose a square on the board where your pieces match the pattern on the card. The pattern can be rotated (by 90, 180, or 270 degrees). Mirror images and flips also count as a match. The pieces used to summon the being can be the same rank as those depicted in the pattern or higher rank. Empty squares are not important to the pattern. - '''Place a piece of the indicated rank''' (upper left corner of the card) on the square indicated by the white-framed square in the pattern. This square may be empty, unless the pattern says it must be occupied by one of your pieces. If the square is occupied by a piece of the same rank or lower, destroy that piece when you put the new piece on the square. If the square is occupied by a piece of higher rank, you cannot summon the being. If all your pieces of that type are already on the board, you may still be able to summon the being by picking up a piece that is not required for the pattern and use it as the new piece. - Once the new piece is on the board, '''resolve the effect''' printed on the card. - After resolving the effect, discard the card. == Invoking a flare == You can invoke a flare on your turn before or after any action. To invoke a flare, you must meet at least one of the criteria: - You meet the upper criterion if your opponent has '''that many more upgraded pieces''' (heroic and legendary) on the board than you. - You meet the lower criterion if your opponent has '''that many more pieces (total)''' on the board than you. If you meet the upper criterion, you resolve the upper effect. If you meet the lower criterion, you resolve the lower effect. If you meet both, you resolve the upper effect first, then the lower. Once the card has been resolved, discard it. == Resolving effects of beings and flares == No other action can be taken and no flare can be invoked until the entire effect of the card is resolved. Some parts of an effect may be optional: - May indicates that a certain part of an effect is optional. - Up to always includes 0. Any parts that are not specified as optional are mandatory. If an effect cannot be performed fully, do the parts that can be done. When a card uses its own name, it is referring to the piece on the board that represents the summoned being. '''Keywords''': - Upgraded piece: a heroic or legendary piece. - Non-legendary piece: a common or heroic piece. - Piece: If a piece is not specified as belonging to you or an opponent, then the effect includes any player's piece. - Marked space: a colored space in the pattern. If the text does not refer to marked spaces, the colored spaces in the pattern are just illustrational. - Adjacent square: one of eight squares sharing an edge (orthogonally adjacent) or a corner (diagonally adjacent) with a given square. If the given square is not specified, assume it is the square currently occupied by the newly summoned piece. - Distance: the shortest number of moves required to get from one square to another. For example, adjacent squares are at distance 1. - Move: A move is always onto an adjacent square. A move onto an occupied square destroys the piece that was there. - Standard move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Combat move: This type of move can be only onto an empty square or a square occupied by a piece of equal or lower rank. - Standard leap and combat leap: A leap is the same as a move, except the square doesn’t have to be adjacent. If not specified, a leap can be onto any square on the board. - Place: Like the “place” action. However, if there is no piece of the specified color and rank available, the piece cannot be placed. - Upgrade: Legendary pieces cannot be upgraded. To upgrade a common piece, flip it over. To upgrade a heroic piece, remove it and replace it with a legendary piece. If none is available, the heroic piece cannot be upgraded. - Downgrade: Common pieces cannot be downgraded. To downgrade a heroic piece, flip it over. To downgrade a legendary piece, replace it with a heroic piece. If none is available, the legendary piece cannot be downgraded. - Destroy: To destroy a piece, remove it from the board. - Convert: To convert an enemy piece, replace it with one of your pieces of the same rank (unless a different rank is specified). When keeping track of '''how many enemy pieces you destroyed''', count pieces you destroyed during summoning, pieces you destroyed with moves and leaps, pieces you destroyed with a “destroy” effect, and pieces you converted. Neither upgrading nor downgrading ever counts as destroying a piece. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. ---- These rules are extracted from CGE's full rules for Tash-Kalar. 51a323e344f6296fb68560a941aa4b5d515c41ca 1313 1312 2014-12-29T17:07:14Z Tolkienistka 7526 /* Game forms */ wikitext text/x-wiki == Форма игры == На Board Game Arena, в Таш-Калар могут играть только 2 игрока, в 2 различных форматах: - '''Высокая форма''': Игроки набирают очки для задач, а также для легендарных частей на доске в настоящее время . - '''Смертельная Дуэль''': Нет задач. Игроки зарабатывают очки для уничтожения вражеских частей; для вызова легендарных частей; и, когда их противник вызывает вспышку. The actual board game also features Deathmatch Melee for 3 or 4 players, and team play. == Setup == Each player draws 6 cards : 3 beings from his or her own deck, 2 legends, and 1 flare. In '''High Form''', 3 tasks are revealed that may be claimed, along with a fourth "next task". In '''Deathmatch''', the player who plays second puts one common piece of each color on the game board, on marked squares. == Game play == Players take turns in clockwise order, beginning with the starting player. Each turn, you have 2 actions. Exception: The starting player has only 1 action on his or her first turn. Possible actions: - '''Place 1 common piece''' of your color on any empty square. If you have none left to place, you begin this action by picking up 1 of your common or heroic pieces, then place it as a common piece. - '''Summon a being'''. (See below.) - '''Discard 1 being''' that you drew from your deck. If you do, you may also return one or more of your other cards to the bottoms of their decks. Actions can be done in any order. You can do more than one “place” or “summon” action per turn (but no more than one “discard” action). You have to use all your actions. You can invoke a flare (see below) before or after any action. Invoking a flare does not cost you an action. Finish your turn by drawing cards so that you end up with 3 beings from your deck, 2 legends, and 1 flare. If you draw the last card in your deck, you may end up with fewer than 3. '''High Form''': At the end of the turn, you may claim exactly 1 of the current tasks, if you meet its criteria. '''Deathmatch''': At the end of your turn, score points for destroyed enemy pieces: 2 points for legendary, 1 point for heroic, 1 point for each pair of common pieces. You get no points for destroying your own pieces. You get no points for an un- paired common piece. Also score 1 point each time you summon a legend. (Upgrading a heroic piece does not count as “summoning a legend”.) == Summoning a being == To summon a being, use 1 action and do the following: - '''Play the card''' from your hand and choose a square on the board where your pieces match the pattern on the card. The pattern can be rotated (by 90, 180, or 270 degrees). Mirror images and flips also count as a match. The pieces used to summon the being can be the same rank as those depicted in the pattern or higher rank. Empty squares are not important to the pattern. - '''Place a piece of the indicated rank''' (upper left corner of the card) on the square indicated by the white-framed square in the pattern. This square may be empty, unless the pattern says it must be occupied by one of your pieces. If the square is occupied by a piece of the same rank or lower, destroy that piece when you put the new piece on the square. If the square is occupied by a piece of higher rank, you cannot summon the being. If all your pieces of that type are already on the board, you may still be able to summon the being by picking up a piece that is not required for the pattern and use it as the new piece. - Once the new piece is on the board, '''resolve the effect''' printed on the card. - After resolving the effect, discard the card. == Invoking a flare == You can invoke a flare on your turn before or after any action. To invoke a flare, you must meet at least one of the criteria: - You meet the upper criterion if your opponent has '''that many more upgraded pieces''' (heroic and legendary) on the board than you. - You meet the lower criterion if your opponent has '''that many more pieces (total)''' on the board than you. If you meet the upper criterion, you resolve the upper effect. If you meet the lower criterion, you resolve the lower effect. If you meet both, you resolve the upper effect first, then the lower. Once the card has been resolved, discard it. == Resolving effects of beings and flares == No other action can be taken and no flare can be invoked until the entire effect of the card is resolved. Some parts of an effect may be optional: - May indicates that a certain part of an effect is optional. - Up to always includes 0. Any parts that are not specified as optional are mandatory. If an effect cannot be performed fully, do the parts that can be done. When a card uses its own name, it is referring to the piece on the board that represents the summoned being. '''Keywords''': - Upgraded piece: a heroic or legendary piece. - Non-legendary piece: a common or heroic piece. - Piece: If a piece is not specified as belonging to you or an opponent, then the effect includes any player's piece. - Marked space: a colored space in the pattern. If the text does not refer to marked spaces, the colored spaces in the pattern are just illustrational. - Adjacent square: one of eight squares sharing an edge (orthogonally adjacent) or a corner (diagonally adjacent) with a given square. If the given square is not specified, assume it is the square currently occupied by the newly summoned piece. - Distance: the shortest number of moves required to get from one square to another. For example, adjacent squares are at distance 1. - Move: A move is always onto an adjacent square. A move onto an occupied square destroys the piece that was there. - Standard move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Combat move: This type of move can be only onto an empty square or a square occupied by a piece of equal or lower rank. - Standard leap and combat leap: A leap is the same as a move, except the square doesn’t have to be adjacent. If not specified, a leap can be onto any square on the board. - Place: Like the “place” action. However, if there is no piece of the specified color and rank available, the piece cannot be placed. - Upgrade: Legendary pieces cannot be upgraded. To upgrade a common piece, flip it over. To upgrade a heroic piece, remove it and replace it with a legendary piece. If none is available, the heroic piece cannot be upgraded. - Downgrade: Common pieces cannot be downgraded. To downgrade a heroic piece, flip it over. To downgrade a legendary piece, replace it with a heroic piece. If none is available, the legendary piece cannot be downgraded. - Destroy: To destroy a piece, remove it from the board. - Convert: To convert an enemy piece, replace it with one of your pieces of the same rank (unless a different rank is specified). When keeping track of '''how many enemy pieces you destroyed''', count pieces you destroyed during summoning, pieces you destroyed with moves and leaps, pieces you destroyed with a “destroy” effect, and pieces you converted. Neither upgrading nor downgrading ever counts as destroying a piece. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. ---- These rules are extracted from CGE's full rules for Tash-Kalar. 84d89e98e3247629b5b88a2fee798a886efd25f4 1336 1313 2015-01-18T00:34:54Z Squarerootofthree 5668 Undo revision 1313 by [[Special:Contributions/Tolkienistka|Tolkienistka]] ([[User talk:Tolkienistka|talk]]) wikitext text/x-wiki == Game forms == On Board Game Arena, Tash-Kalar may be played only by 2 players, and in 2 distinct forms : - '''The High Form''': Players score points for tasks and for legendary pieces currently on the board. - '''Deathmatch Duel''': No tasks. Players score points for destroying enemy pieces, for summoning legendary beings, and when their opponent invokes a flare. The actual board game also features Deathmatch Melee for 3 or 4 players, and team play. == Setup == Each player draws 6 cards : 3 beings from his or her own deck, 2 legends, and 1 flare. In '''High Form''', 3 tasks are revealed that may be claimed, along with a fourth "next task". In '''Deathmatch''', the player who plays second puts one common piece of each color on the game board, on marked squares. == Game play == Players take turns in clockwise order, beginning with the starting player. Each turn, you have 2 actions. Exception: The starting player has only 1 action on his or her first turn. Possible actions: - '''Place 1 common piece''' of your color on any empty square. If you have none left to place, you begin this action by picking up 1 of your common or heroic pieces, then place it as a common piece. - '''Summon a being'''. (See below.) - '''Discard 1 being''' that you drew from your deck. If you do, you may also return one or more of your other cards to the bottoms of their decks. Actions can be done in any order. You can do more than one “place” or “summon” action per turn (but no more than one “discard” action). You have to use all your actions. You can invoke a flare (see below) before or after any action. Invoking a flare does not cost you an action. Finish your turn by drawing cards so that you end up with 3 beings from your deck, 2 legends, and 1 flare. If you draw the last card in your deck, you may end up with fewer than 3. '''High Form''': At the end of the turn, you may claim exactly 1 of the current tasks, if you meet its criteria. '''Deathmatch''': At the end of your turn, score points for destroyed enemy pieces: 2 points for legendary, 1 point for heroic, 1 point for each pair of common pieces. You get no points for destroying your own pieces. You get no points for an un- paired common piece. Also score 1 point each time you summon a legend. (Upgrading a heroic piece does not count as “summoning a legend”.) == Summoning a being == To summon a being, use 1 action and do the following: - '''Play the card''' from your hand and choose a square on the board where your pieces match the pattern on the card. The pattern can be rotated (by 90, 180, or 270 degrees). Mirror images and flips also count as a match. The pieces used to summon the being can be the same rank as those depicted in the pattern or higher rank. Empty squares are not important to the pattern. - '''Place a piece of the indicated rank''' (upper left corner of the card) on the square indicated by the white-framed square in the pattern. This square may be empty, unless the pattern says it must be occupied by one of your pieces. If the square is occupied by a piece of the same rank or lower, destroy that piece when you put the new piece on the square. If the square is occupied by a piece of higher rank, you cannot summon the being. If all your pieces of that type are already on the board, you may still be able to summon the being by picking up a piece that is not required for the pattern and use it as the new piece. - Once the new piece is on the board, '''resolve the effect''' printed on the card. - After resolving the effect, discard the card. == Invoking a flare == You can invoke a flare on your turn before or after any action. To invoke a flare, you must meet at least one of the criteria: - You meet the upper criterion if your opponent has '''that many more upgraded pieces''' (heroic and legendary) on the board than you. - You meet the lower criterion if your opponent has '''that many more pieces (total)''' on the board than you. If you meet the upper criterion, you resolve the upper effect. If you meet the lower criterion, you resolve the lower effect. If you meet both, you resolve the upper effect first, then the lower. Once the card has been resolved, discard it. == Resolving effects of beings and flares == No other action can be taken and no flare can be invoked until the entire effect of the card is resolved. Some parts of an effect may be optional: - May indicates that a certain part of an effect is optional. - Up to always includes 0. Any parts that are not specified as optional are mandatory. If an effect cannot be performed fully, do the parts that can be done. When a card uses its own name, it is referring to the piece on the board that represents the summoned being. '''Keywords''': - Upgraded piece: a heroic or legendary piece. - Non-legendary piece: a common or heroic piece. - Piece: If a piece is not specified as belonging to you or an opponent, then the effect includes any player's piece. - Marked space: a colored space in the pattern. If the text does not refer to marked spaces, the colored spaces in the pattern are just illustrational. - Adjacent square: one of eight squares sharing an edge (orthogonally adjacent) or a corner (diagonally adjacent) with a given square. If the given square is not specified, assume it is the square currently occupied by the newly summoned piece. - Distance: the shortest number of moves required to get from one square to another. For example, adjacent squares are at distance 1. - Move: A move is always onto an adjacent square. A move onto an occupied square destroys the piece that was there. - Standard move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Combat move: This type of move can be only onto an empty square or a square occupied by a piece of equal or lower rank. - Standard leap and combat leap: A leap is the same as a move, except the square doesn’t have to be adjacent. If not specified, a leap can be onto any square on the board. - Place: Like the “place” action. However, if there is no piece of the specified color and rank available, the piece cannot be placed. - Upgrade: Legendary pieces cannot be upgraded. To upgrade a common piece, flip it over. To upgrade a heroic piece, remove it and replace it with a legendary piece. If none is available, the heroic piece cannot be upgraded. - Downgrade: Common pieces cannot be downgraded. To downgrade a heroic piece, flip it over. To downgrade a legendary piece, replace it with a heroic piece. If none is available, the legendary piece cannot be downgraded. - Destroy: To destroy a piece, remove it from the board. - Convert: To convert an enemy piece, replace it with one of your pieces of the same rank (unless a different rank is specified). When keeping track of '''how many enemy pieces you destroyed''', count pieces you destroyed during summoning, pieces you destroyed with moves and leaps, pieces you destroyed with a “destroy” effect, and pieces you converted. Neither upgrading nor downgrading ever counts as destroying a piece. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. ---- These rules are extracted from CGE's full rules for Tash-Kalar. 51a323e344f6296fb68560a941aa4b5d515c41ca Gamehelpredseven 0 178 1311 2014-12-25T23:11:28Z Sparr 7369 First rules summary, from rulebook wikitext text/x-wiki The rules of Red are simple: Have the best card! But will you still be playing the same game when your turn ends? If you’re not winning the current game at the end of your turn, you’re out, and the last person standing wins the round. The deck consists of 49 cards, numbered 1-7, in each of seven rainbow colors. A 7 is always higher than a 6, but when comparing two 6s, a Red 6 is higher than an Orange 6, and so on down the color spectrum (Red, Orange, Yellow, Green, Blue, Indigo, Violet). To play Red7, deal out a seven-card hand to each player, and then deal one more card faceup in front of each player to start their Palette. Start a Canvas pile with the You are Playing Red card. The top card of the Canvas pile determines what the rules are. The player with the highest card on their Palette is currently the best at Red, so the player to that player’s left goes first. On your turn, you must take one of the following actions: 1. Play a card faceup from your hand to your Palette. 2. Discard a card from your hand to the Canvas to change the game to the rule listed on the card. You must be winning the new game after you do this. 3. Play a card from your hand to your Palette AND THEN discard a card to the Canvas. You must be winning the game after you do this. 4. Do nothing, and lose. You might want to do this intentionally when playing Advanced Red7 to limit the number of points an opponent will score. If your hand is empty, you must do this. If you are not winning the game at the end of your turn, you lose and are out of the round. Place your hand cards and Palette cards facedown. If you start your turn and you’re the only player left, you win the round! You are winning a game if your Palette contains more cards that meet the Canvas rule than any other player. Ignore the other cards in your Palette. In case of a tie, whoever has the highest card of those following the Canvas rule (following color order if necessary) is winning. If you have no cards in your hand at the start of a turn, you lose and are out of the round. Once you’ve played Red7 a few times, you might be ready for some advanced rules, and scoring between rounds! Advanced Red7 has two additional rules. When you discard a card to the Canvas, if the number on that card is higher than the total number of cards in your Palette, you may draw an additional card from the Draw Deck (unless the Draw Deck is empty). The winner of a round scores points. If you win a round, take all the cards from your Palette that meet the current rule and place them under your reference card. For example, if you won Blue by having the most differently colored cards on your Palette, take the highest card of each color from your Palette and place them under your reference card. The next hand is dealt without those cards, as they are now your score pile. Cards are worth their face value in points. If there aren’t enough cards to deal out a new hand to each player, the game ends and the player with the highest score wins. POINTS TO WIN 2 PLAYERS: 40 POINTS 3 PLAYERS: 35 POINTS 4 PLAYERS: 30 POINTS ACTIONS You might also notice that the four odd-numbered cards have icons in their corners. These represent an optional rule for actions, meant for experienced Red7 players. They can be mixed with either Basic or Advanced Red7. By these rules, when you play a 1, 3, 5, or 7 to your Palette, you MUST perform that card’s action if you can. 7: Discard one other card from your Palette to the Canvas. It must be a valid discard, as it becomes the new rule. This means you must be winning the new color’s game. 5: Play another card from your hand to your Palette. You can still discard to the Canvas if you wish after you’ve finished playing to your Palette this turn. 3: Draw a card from the Draw Deck if you can. 1: Take a card from another player’s Palette, and place it face down on top of the Draw Deck. You may not discard that player’s only Palette card. 099cb8181ff0aaa0af5f172c7bc643c19dfe76f1 Gamehelppolis 0 179 1314 2015-01-08T01:22:42Z Jmaydet 7639 Created page with " == Development Actions == 1. '''Create Hoplites:''' Only in one polis per turn; pay 1 metal (or silver) per hoplite 2. '''Create Galleys:''' Only in one polis per turn; pay ..." wikitext text/x-wiki == Development Actions == 1. '''Create Hoplites:''' Only in one polis per turn; pay 1 metal (or silver) per hoplite 2. '''Create Galleys:''' Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). 3. '''Create Merchants:''' Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == 5. '''Move Hoplites:''' Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories); territories controlled by opponent block movement. 6. '''Move Galleys:''' Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. 7. '''Besiege Polis:''' Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: • If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). • If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. 8. '''Collection:''' Take resources corresponding to hoplite placement in Tribute Box. Place disk. No Prestige cost for action in home region. == Political Actions == 9. '''Trade:''' Move one merchant via free trade route to Foreign Market and place it on available shipload: • Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). • Purchase (silver paid for wheat); then increase market value (roll die twice; use higher result to move marker left). 10. '''Move Proxenos:''' Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). 11. '''Redeem Proxenos:''' Pay 2 silver to opponent; place Proxenos in capital. 12. '''Instigate Civil War:''' Proxenos needed; action costs 2 Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: • not matching: defender loses 1 unit, attacker gains Prestige on card. • matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: 1. not enough cards are left in the Combat Card deck. 2. one player retreats (and pays 1 Prestige to opponent). 3. one player has less than 2 units left. == End of the Round == 1. '''Projects:''' all are completed, and award immediate Prestige. 2. '''Supply:''' player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. 3. '''Growth:''' increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. 4. '''Megalopolis:''' 1 Prestige awarded for every polis exceeding Base Population. 5. '''Storage:''' halve amount of oil, wine, and wheat in storage (rounded up) 6. '''Phoros:''' exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == 1. A player cannot supply enough wheat/Prestige to feed his capital. 2. A player does not have any Prestige left after “End of Round” phase. 3. The fourth round (5β) has been finished. == Final Score == • total of Population Cubes in all poleis, plus • current Prestige, plus • ”Prestige for Posterity” (on project tiles). f20ad4ae8f9ade98952e6a5f96611015f0ddac9a 1315 1314 2015-01-08T01:24:52Z Jmaydet 7639 /* Development Actions */ wikitext text/x-wiki == Development Actions == '''1. Create Hoplites:''' Only in one polis per turn; pay 1 metal (or silver) per hoplite '''2. Create Galleys:''' Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). '''3. Create Merchants:''' Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == 5. '''Move Hoplites:''' Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories); territories controlled by opponent block movement. 6. '''Move Galleys:''' Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. 7. '''Besiege Polis:''' Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: • If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). • If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. 8. '''Collection:''' Take resources corresponding to hoplite placement in Tribute Box. Place disk. No Prestige cost for action in home region. == Political Actions == 9. '''Trade:''' Move one merchant via free trade route to Foreign Market and place it on available shipload: • Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). • Purchase (silver paid for wheat); then increase market value (roll die twice; use higher result to move marker left). 10. '''Move Proxenos:''' Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). 11. '''Redeem Proxenos:''' Pay 2 silver to opponent; place Proxenos in capital. 12. '''Instigate Civil War:''' Proxenos needed; action costs 2 Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: • not matching: defender loses 1 unit, attacker gains Prestige on card. • matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: 1. not enough cards are left in the Combat Card deck. 2. one player retreats (and pays 1 Prestige to opponent). 3. one player has less than 2 units left. == End of the Round == 1. '''Projects:''' all are completed, and award immediate Prestige. 2. '''Supply:''' player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. 3. '''Growth:''' increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. 4. '''Megalopolis:''' 1 Prestige awarded for every polis exceeding Base Population. 5. '''Storage:''' halve amount of oil, wine, and wheat in storage (rounded up) 6. '''Phoros:''' exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == 1. A player cannot supply enough wheat/Prestige to feed his capital. 2. A player does not have any Prestige left after “End of Round” phase. 3. The fourth round (5β) has been finished. == Final Score == • total of Population Cubes in all poleis, plus • current Prestige, plus • ”Prestige for Posterity” (on project tiles). 4ac06ea2cdffac5b828e22102125c5de9a947922 1316 1315 2015-01-08T01:25:27Z Jmaydet 7639 /* Military Actions (cost 1 Prestige) */ wikitext text/x-wiki == Development Actions == '''1. Create Hoplites:''' Only in one polis per turn; pay 1 metal (or silver) per hoplite '''2. Create Galleys:''' Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). '''3. Create Merchants:''' Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == '''5. Move Hoplites:''' Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories); territories controlled by opponent block movement. '''6. Move Galleys:''' Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. '''7. Besiege Polis:''' Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: • If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). • If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. '''8. Collection:''' Take resources corresponding to hoplite placement in Tribute Box. Place disk. No Prestige cost for action in home region. == Political Actions == 9. '''Trade:''' Move one merchant via free trade route to Foreign Market and place it on available shipload: • Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). • Purchase (silver paid for wheat); then increase market value (roll die twice; use higher result to move marker left). 10. '''Move Proxenos:''' Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). 11. '''Redeem Proxenos:''' Pay 2 silver to opponent; place Proxenos in capital. 12. '''Instigate Civil War:''' Proxenos needed; action costs 2 Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: • not matching: defender loses 1 unit, attacker gains Prestige on card. • matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: 1. not enough cards are left in the Combat Card deck. 2. one player retreats (and pays 1 Prestige to opponent). 3. one player has less than 2 units left. == End of the Round == 1. '''Projects:''' all are completed, and award immediate Prestige. 2. '''Supply:''' player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. 3. '''Growth:''' increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. 4. '''Megalopolis:''' 1 Prestige awarded for every polis exceeding Base Population. 5. '''Storage:''' halve amount of oil, wine, and wheat in storage (rounded up) 6. '''Phoros:''' exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == 1. A player cannot supply enough wheat/Prestige to feed his capital. 2. A player does not have any Prestige left after “End of Round” phase. 3. The fourth round (5β) has been finished. == Final Score == • total of Population Cubes in all poleis, plus • current Prestige, plus • ”Prestige for Posterity” (on project tiles). d7c87757f522cf56d390fa8dc61d14aad8c22d0a 1317 1316 2015-01-08T01:26:22Z Jmaydet 7639 /* Political Actions */ wikitext text/x-wiki == Development Actions == '''1. Create Hoplites:''' Only in one polis per turn; pay 1 metal (or silver) per hoplite '''2. Create Galleys:''' Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). '''3. Create Merchants:''' Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == '''5. Move Hoplites:''' Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories); territories controlled by opponent block movement. '''6. Move Galleys:''' Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. '''7. Besiege Polis:''' Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: • If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). • If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. '''8. Collection:''' Take resources corresponding to hoplite placement in Tribute Box. Place disk. No Prestige cost for action in home region. == Political Actions == '''9. Trade:''' Move one merchant via free trade route to Foreign Market and place it on available shipload: • Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). • Purchase (silver paid for wheat); then increase market value (roll die twice; use higher result to move marker left). '''10. Move Proxenos:''' Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). '''11. Redeem Proxenos:''' Pay 2 silver to opponent; place Proxenos in capital. '''12. Instigate Civil War:''' Proxenos needed; action costs 2 Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: • not matching: defender loses 1 unit, attacker gains Prestige on card. • matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: 1. not enough cards are left in the Combat Card deck. 2. one player retreats (and pays 1 Prestige to opponent). 3. one player has less than 2 units left. == End of the Round == 1. '''Projects:''' all are completed, and award immediate Prestige. 2. '''Supply:''' player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. 3. '''Growth:''' increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. 4. '''Megalopolis:''' 1 Prestige awarded for every polis exceeding Base Population. 5. '''Storage:''' halve amount of oil, wine, and wheat in storage (rounded up) 6. '''Phoros:''' exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == 1. A player cannot supply enough wheat/Prestige to feed his capital. 2. A player does not have any Prestige left after “End of Round” phase. 3. The fourth round (5β) has been finished. == Final Score == • total of Population Cubes in all poleis, plus • current Prestige, plus • ”Prestige for Posterity” (on project tiles). 6f1ea8536c170e141600941dfec0f121274b2d58 1318 1317 2015-01-08T01:27:34Z Jmaydet 7639 wikitext text/x-wiki == Development Actions == '''1. Create Hoplites:''' Only in one polis per turn; pay 1 metal (or silver) per hoplite '''2. Create Galleys:''' Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). '''3. Create Merchants:''' Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == '''5. Move Hoplites:''' Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories); territories controlled by opponent block movement. '''6. Move Galleys:''' Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. '''7. Besiege Polis:''' Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: • If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). • If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. '''8. Collection:''' Take resources corresponding to hoplite placement in Tribute Box. Place disk. No Prestige cost for action in home region. == Political Actions == '''9. Trade:''' Move one merchant via free trade route to Foreign Market and place it on available shipload: • Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). • Purchase (silver paid for wheat); then increase market value (roll die twice; use higher result to move marker left). '''10. Move Proxenos:''' Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). '''11. Redeem Proxenos:''' Pay 2 silver to opponent; place Proxenos in capital. '''12. Instigate Civil War:''' Proxenos needed; action costs 2 Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: • not matching: defender loses 1 unit, attacker gains Prestige on card. • matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: 1. not enough cards are left in the Combat Card deck. 2. one player retreats (and pays 1 Prestige to opponent). 3. one player has less than 2 units left. == End of the Round == '''1. Projects:''' all are completed, and award immediate Prestige. '''2. Supply:''' player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. '''3. Growth:''' increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. '''4. Megalopolis:''' 1 Prestige awarded for every polis exceeding Base Population. '''5. Storage:''' halve amount of oil, wine, and wheat in storage (rounded up) '''6. Phoros:''' exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == 1. A player cannot supply enough wheat/Prestige to feed his capital. 2. A player does not have any Prestige left after “End of Round” phase. 3. The fourth round (5β) has been finished. == Final Score == • total of Population Cubes in all poleis, plus • current Prestige, plus • ”Prestige for Posterity” (on project tiles). aa1112ce2249ca988b10c41114406c5918454971 1319 1318 2015-01-08T01:28:35Z Jmaydet 7639 /* Development Actions */ wikitext text/x-wiki == Development Actions == '''# Create Hoplites:''' Only in one polis per turn; pay 1 metal (or silver) per hoplite '''# Create Galleys:''' Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). '''# Create Merchants:''' Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == '''5. Move Hoplites:''' Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories); territories controlled by opponent block movement. '''6. Move Galleys:''' Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. '''7. Besiege Polis:''' Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: • If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). • If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. '''8. Collection:''' Take resources corresponding to hoplite placement in Tribute Box. Place disk. No Prestige cost for action in home region. == Political Actions == '''9. Trade:''' Move one merchant via free trade route to Foreign Market and place it on available shipload: • Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). • Purchase (silver paid for wheat); then increase market value (roll die twice; use higher result to move marker left). '''10. Move Proxenos:''' Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). '''11. Redeem Proxenos:''' Pay 2 silver to opponent; place Proxenos in capital. '''12. Instigate Civil War:''' Proxenos needed; action costs 2 Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: • not matching: defender loses 1 unit, attacker gains Prestige on card. • matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: 1. not enough cards are left in the Combat Card deck. 2. one player retreats (and pays 1 Prestige to opponent). 3. one player has less than 2 units left. == End of the Round == '''1. Projects:''' all are completed, and award immediate Prestige. '''2. Supply:''' player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. '''3. Growth:''' increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. '''4. Megalopolis:''' 1 Prestige awarded for every polis exceeding Base Population. '''5. Storage:''' halve amount of oil, wine, and wheat in storage (rounded up) '''6. Phoros:''' exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == 1. A player cannot supply enough wheat/Prestige to feed his capital. 2. A player does not have any Prestige left after “End of Round” phase. 3. The fourth round (5β) has been finished. == Final Score == • total of Population Cubes in all poleis, plus • current Prestige, plus • ”Prestige for Posterity” (on project tiles). 4edf9cd9340041c4e0b9ad4b47ef1cc466648b65 1320 1319 2015-01-08T01:28:52Z Jmaydet 7639 /* Development Actions */ wikitext text/x-wiki == Development Actions == # Create Hoplites: Only in one polis per turn; pay 1 metal (or silver) per hoplite # Create Galleys: Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). # Create Merchants: Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == '''5. Move Hoplites:''' Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories); territories controlled by opponent block movement. '''6. Move Galleys:''' Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. '''7. Besiege Polis:''' Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: • If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). • If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. '''8. Collection:''' Take resources corresponding to hoplite placement in Tribute Box. Place disk. No Prestige cost for action in home region. == Political Actions == '''9. Trade:''' Move one merchant via free trade route to Foreign Market and place it on available shipload: • Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). • Purchase (silver paid for wheat); then increase market value (roll die twice; use higher result to move marker left). '''10. Move Proxenos:''' Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). '''11. Redeem Proxenos:''' Pay 2 silver to opponent; place Proxenos in capital. '''12. Instigate Civil War:''' Proxenos needed; action costs 2 Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: • not matching: defender loses 1 unit, attacker gains Prestige on card. • matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: 1. not enough cards are left in the Combat Card deck. 2. one player retreats (and pays 1 Prestige to opponent). 3. one player has less than 2 units left. == End of the Round == '''1. Projects:''' all are completed, and award immediate Prestige. '''2. Supply:''' player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. '''3. Growth:''' increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. '''4. Megalopolis:''' 1 Prestige awarded for every polis exceeding Base Population. '''5. Storage:''' halve amount of oil, wine, and wheat in storage (rounded up) '''6. Phoros:''' exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == 1. A player cannot supply enough wheat/Prestige to feed his capital. 2. A player does not have any Prestige left after “End of Round” phase. 3. The fourth round (5β) has been finished. == Final Score == • total of Population Cubes in all poleis, plus • current Prestige, plus • ”Prestige for Posterity” (on project tiles). 890e15f6915accc6d1932ce16606163f3de0bacf 1321 1320 2015-01-08T01:29:57Z Jmaydet 7639 wikitext text/x-wiki == Development Actions == # Create Hoplites: Only in one polis per turn; pay 1 metal (or silver) per hoplite # Create Galleys: Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). # Create Merchants: Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == # Move Hoplites: Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories); territories controlled by opponent block movement. # Move Galleys: Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. # Besiege Polis: Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: ## If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). ## If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. # Collection: Take resources corresponding to hoplite placement in Tribute Box. Place disk. No Prestige cost for action in home region. == Political Actions == 9. Trade: Move one merchant via free trade route to Foreign Market and place it on available shipload: • Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). • Purchase (silver paid for wheat); then increase market value (roll die twice; use higher result to move marker left). 10. Move Proxenos: Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). 11. Redeem Proxenos: Pay 2 silver to opponent; place Proxenos in capital. 12. Instigate Civil War: Proxenos needed; action costs 2 Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: • not matching: defender loses 1 unit, attacker gains Prestige on card. • matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: 1. not enough cards are left in the Combat Card deck. 2. one player retreats (and pays 1 Prestige to opponent). 3. one player has less than 2 units left. == End of the Round == 1. Projects: all are completed, and award immediate Prestige. 2. Supply: player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. 3. Growth: increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. 4. Megalopolis: 1 Prestige awarded for every polis exceeding Base Population. 5. Storage: halve amount of oil, wine, and wheat in storage (rounded up) 6. Phoros: exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == 1. A player cannot supply enough wheat/Prestige to feed his capital. 2. A player does not have any Prestige left after “End of Round” phase. 3. The fourth round (5β) has been finished. == Final Score == • total of Population Cubes in all poleis, plus • current Prestige, plus • ”Prestige for Posterity” (on project tiles). 35f2dbb20754fc5e5ed7af972d73905d095017f5 1322 1321 2015-01-08T01:31:44Z Jmaydet 7639 wikitext text/x-wiki == Development Actions == # Create Hoplites: Only in one polis per turn; pay 1 metal (or silver) per hoplite # Create Galleys: Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). # Create Merchants: Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == # Move Hoplites: Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories); territories controlled by opponent block movement. # Move Galleys: Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. # Besiege Polis: Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: ## If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). ## If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. # Collection: Take resources corresponding to hoplite placement in Tribute Box. Place disk. No Prestige cost for action in home region. == Political Actions == # Trade: Move one merchant via free trade route to Foreign Market and place it on available shipload: ## Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). ## Purchase (silver paid for wheat); then increase market value (roll die twice; use higher result to move marker left). # Move Proxenos: Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). # Redeem Proxenos: Pay 2 silver to opponent; place Proxenos in capital. # Instigate Civil War: Proxenos needed; action costs 2 Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: # not matching: defender loses 1 unit, attacker gains Prestige on card. # matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: # not enough cards are left in the Combat Card deck. # one player retreats (and pays 1 Prestige to opponent). # one player has less than 2 units left. == End of the Round == # Projects: all are completed, and award immediate Prestige. # Supply: player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. # Growth: increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. # Megalopolis: 1 Prestige awarded for every polis exceeding Base Population. # Storage: halve amount of oil, wine, and wheat in storage (rounded up) # Phoros: exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == # A player cannot supply enough wheat/Prestige to feed his capital. # A player does not have any Prestige left after “End of Round” phase. # The fourth round (5β) has been finished. == Final Score == - total of Population Cubes in all poleis, plus - current Prestige, plus - ”Prestige for Posterity” (on project tiles). e1c4a53d41b0e2a038d045dfc14b308762714e74 1323 1322 2015-01-08T01:33:09Z Jmaydet 7639 wikitext text/x-wiki == Development Actions == # Create Hoplites: Only in one polis per turn; pay 1 metal (or silver) per hoplite # Create Galleys: Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). # Create Merchants: Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == # Move Hoplites: Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories); territories controlled by opponent block movement. # Move Galleys: Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. # Besiege Polis: Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: * If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). * If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. # Collection: Take resources corresponding to hoplite placement in Tribute Box. Place disk. No Prestige cost for action in home region. == Political Actions == # Trade: Move one merchant via free trade route to Foreign Market and place it on available shipload: * Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). * Purchase (silver paid for wheat); then increase market value (roll die twice; use higher result to move marker left). # Move Proxenos: Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). # Redeem Proxenos: Pay 2 silver to opponent; place Proxenos in capital. # Instigate Civil War: Proxenos needed; action costs 2 Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: * not matching: defender loses 1 unit, attacker gains Prestige on card. * matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: # not enough cards are left in the Combat Card deck. # one player retreats (and pays 1 Prestige to opponent). # one player has less than 2 units left. == End of the Round == # Projects: all are completed, and award immediate Prestige. # Supply: player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. # Growth: increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. # Megalopolis: 1 Prestige awarded for every polis exceeding Base Population. # Storage: halve amount of oil, wine, and wheat in storage (rounded up) # Phoros: exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == # A player cannot supply enough wheat/Prestige to feed his capital. # A player does not have any Prestige left after “End of Round” phase. # The fourth round (5β) has been finished. == Final Score == * total of Population Cubes in all poleis, plus * current Prestige, plus * ”Prestige for Posterity” (on project tiles). 9960e8defe347ed8efce30906945c9203e7372fa 1324 1323 2015-01-08T01:34:25Z Jmaydet 7639 /* Military Actions (cost 1 Prestige) */ wikitext text/x-wiki == Development Actions == # Create Hoplites: Only in one polis per turn; pay 1 metal (or silver) per hoplite # Create Galleys: Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). # Create Merchants: Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == # Move Hoplites: Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories); territories controlled by opponent block movement. # Move Galleys: Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. # Besiege Polis: Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: ** If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). ** If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. # Collection: Take resources corresponding to hoplite placement in Tribute Box. Place disk. No Prestige cost for action in home region. == Political Actions == # Trade: Move one merchant via free trade route to Foreign Market and place it on available shipload: * Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). * Purchase (silver paid for wheat); then increase market value (roll die twice; use higher result to move marker left). # Move Proxenos: Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). # Redeem Proxenos: Pay 2 silver to opponent; place Proxenos in capital. # Instigate Civil War: Proxenos needed; action costs 2 Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: * not matching: defender loses 1 unit, attacker gains Prestige on card. * matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: # not enough cards are left in the Combat Card deck. # one player retreats (and pays 1 Prestige to opponent). # one player has less than 2 units left. == End of the Round == # Projects: all are completed, and award immediate Prestige. # Supply: player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. # Growth: increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. # Megalopolis: 1 Prestige awarded for every polis exceeding Base Population. # Storage: halve amount of oil, wine, and wheat in storage (rounded up) # Phoros: exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == # A player cannot supply enough wheat/Prestige to feed his capital. # A player does not have any Prestige left after “End of Round” phase. # The fourth round (5β) has been finished. == Final Score == * total of Population Cubes in all poleis, plus * current Prestige, plus * ”Prestige for Posterity” (on project tiles). 71623a80b18ce0974c17d7d4acbc52ca9717cd91 1325 1324 2015-01-08T01:35:31Z Jmaydet 7639 /* Military Actions (cost 1 Prestige) */ wikitext text/x-wiki == Development Actions == # Create Hoplites: Only in one polis per turn; pay 1 metal (or silver) per hoplite # Create Galleys: Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). # Create Merchants: Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == # Move Hoplites: Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories); territories controlled by opponent block movement. # Move Galleys: Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. # Besiege Polis: Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: * If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). * If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. # Collection: Take resources corresponding to hoplite placement in Tribute Box. Place disk. No Prestige cost for action in home region. == Political Actions == # Trade: Move one merchant via free trade route to Foreign Market and place it on available shipload: * Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). * Purchase (silver paid for wheat); then increase market value (roll die twice; use higher result to move marker left). # Move Proxenos: Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). # Redeem Proxenos: Pay 2 silver to opponent; place Proxenos in capital. # Instigate Civil War: Proxenos needed; action costs 2 Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: * not matching: defender loses 1 unit, attacker gains Prestige on card. * matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: # not enough cards are left in the Combat Card deck. # one player retreats (and pays 1 Prestige to opponent). # one player has less than 2 units left. == End of the Round == # Projects: all are completed, and award immediate Prestige. # Supply: player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. # Growth: increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. # Megalopolis: 1 Prestige awarded for every polis exceeding Base Population. # Storage: halve amount of oil, wine, and wheat in storage (rounded up) # Phoros: exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == # A player cannot supply enough wheat/Prestige to feed his capital. # A player does not have any Prestige left after “End of Round” phase. # The fourth round (5β) has been finished. == Final Score == * total of Population Cubes in all poleis, plus * current Prestige, plus * ”Prestige for Posterity” (on project tiles). 9960e8defe347ed8efce30906945c9203e7372fa 1326 1325 2015-01-13T03:33:45Z Jmaydet 7639 /* Political Actions */ wikitext text/x-wiki == Development Actions == # Create Hoplites: Only in one polis per turn; pay 1 metal (or silver) per hoplite # Create Galleys: Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). # Create Merchants: Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == # Move Hoplites: Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories); territories controlled by opponent block movement. # Move Galleys: Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. # Besiege Polis: Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: * If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). * If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. # Collection: Take resources corresponding to hoplite placement in Tribute Box. Place disk. No Prestige cost for action in home region. == Political Actions == # Trade: Move one merchant via free trade route to Foreign Market and place it on available shipload: * Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). * Purchase (silver paid for wheat); then increase market value (roll die twice; use higher result to move marker left). # Move Proxenos: Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). # Redeem Proxenos: Pay 2 silver to opponent; place Proxenos in capital. # Instigate Civil War: Proxenos needed; action costs 2x Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: * not matching: defender loses 1 unit, attacker gains Prestige on card. * matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: # not enough cards are left in the Combat Card deck. # one player retreats (and pays 1 Prestige to opponent). # one player has less than 2 units left. == End of the Round == # Projects: all are completed, and award immediate Prestige. # Supply: player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. # Growth: increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. # Megalopolis: 1 Prestige awarded for every polis exceeding Base Population. # Storage: halve amount of oil, wine, and wheat in storage (rounded up) # Phoros: exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == # A player cannot supply enough wheat/Prestige to feed his capital. # A player does not have any Prestige left after “End of Round” phase. # The fourth round (5β) has been finished. == Final Score == * total of Population Cubes in all poleis, plus * current Prestige, plus * ”Prestige for Posterity” (on project tiles). 105b7609c0e65f732649801e0eea5ac163845981 Gamehelpbattlesheep 0 180 1327 2015-01-17T21:21:13Z Senatorhung 4176 Created page with "The object of the game is to be the player who occupies the most spaces on the pasture. '''Building the Pasture and Initial Placement''': Each player begins with 4 diamond-sh..." wikitext text/x-wiki The object of the game is to be the player who occupies the most spaces on the pasture. '''Building the Pasture and Initial Placement''': Each player begins with 4 diamond-shaped pasture tiles. The first player places one of their pasture tiles on the board. The other players place one of their pasture tiles in turn, with each new tile connecting to the existing pasture on at least one side. This continues until each player has placed all 4 of their pasture tiles. Then, again starting with the first player, each player places their entire stack of 16 sheep on any unoccupied pasture along the OUTSIDE border. Strategy Tip: Games can be won and lost in this phase ! The first player tends to start with an advantage as they have first placement AND first move. You may build the board differently depending on whether you are the first player or one of the subsequent players. In considering initial placement, think about who will act before you and what their likely first move will be. '''Playing the Game''': On your turn, your move consists of splitting a stack of your own sheep into two parts, moving part of the stack in a straight line as far as it can go before hitting another sheep or the border. Click on the stack you wish to split. Then, click on the desired destination pasture hex. This will split your herd in two halves. Click on the original or destination hex to adjust the amount of sheep you want in each herd. You MUST leave at least one sheep on the space on which the original stack was standing. When you are happy with the split, click the 'Validate' option at the top of the game screen. Play continues with each player splitting any one of their stacks. A stack is blocked when it is surrounded by opponents' pieces or the edge, and can no longer be split and moved. '''Ending and Winning the Game''': When all your sheep are blocked, you no longer continue playing. The game ends when only one player can still split a herd. The winner is the player who succeeds in controlling the most pasture land (the most hexes). In the case of a tie, the player who has the largest herd (the number of adjacent spaces occupied by their sheep) wins the game. c522514e4e098be81c512d6a00dd64316a4a543d 1328 1327 2015-01-17T21:24:15Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to be the player who occupies the most spaces on the pasture. '''Building the Pasture and Initial Placement''': Each player begins with 4 diamond-shaped pasture tiles. The first player places one of their pasture tiles on the board. The other players place one of their pasture tiles in turn, with each new tile connecting to the existing pasture on at least one side. This continues until each player has placed all 4 of their pasture tiles. Then, again starting with the first player, each player places their entire stack of 16 sheep on any unoccupied pasture along the OUTSIDE border. Strategy Tip: Games can be won and lost in this phase ! The first player tends to start with an advantage as they have first placement AND first move. You may build the board differently depending on whether you are the first player or one of the subsequent players. In considering initial placement, think about who will act before you and what their likely first move will be. '''Playing the Game''': On your turn, your move consists of splitting a stack of your own sheep into two parts, moving part of the stack in a straight line as far as it can go before hitting another sheep or the border. Click on the stack you wish to split. Then, click on the desired destination pasture hex. This will split your herd in two halves. Click on the original or destination hex to adjust the amount of sheep you want in each herd. You MUST leave at least one sheep on the space on which the original stack was standing. When you are happy with the split, click the 'Validate' option at the top of the game screen. Play continues with each player splitting any one of their stacks. A stack is blocked when it is surrounded by opponents' pieces or the edge, and can no longer be split and moved. Strategy Tip: Watching out for your biggest herd is usually a sound strategy to start with. Watch out for chokepoints that can be easily closed off leaving you without enough room to spread the rest of your herd. Try not to block yourself in and count your sheep carefully ! '''Ending and Winning the Game''': When all your sheep are blocked, you no longer continue playing. The game ends when only one player can still split a herd. The winner is the player who succeeds in controlling the most pasture land (the most hexes). In the case of a tie, the player who has the largest herd (the number of adjacent spaces occupied by their sheep) wins the game. 142128b5f6875b79edf0ee0ed0852069c59e419b 1329 1328 2015-01-17T21:26:03Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to be the player who occupies the most spaces on the pasture. '''Building the Pasture and Initial Placement''': Each player begins with 4 diamond-shaped pasture tiles. The first player places one of their pasture tiles on the board. The other players place one of their pasture tiles in turn, with each new tile connecting to the existing pasture on at least one side. This continues until each player has placed all 4 of their pasture tiles. Then, again starting with the first player, each player places their entire stack of 16 sheep on any unoccupied pasture along the OUTSIDE border. Strategy Tip: Games can be won and lost in this phase ! The first player tends to start with an advantage as they have first placement AND first move. You may build the board differently depending on whether you are the first player or one of the subsequent players. In considering initial placement, think about who will act before you and what their likely first move will be. '''Playing the Game''': On your turn, your move consists of splitting a stack of your own sheep into two parts, moving part of the stack in a straight line as far as it can go before hitting another sheep or the border. Click on the stack you wish to split. Then, click on the desired destination pasture space. This will split your herd in two halves. Click on the original or destination space to adjust the amount of sheep you want in each herd. You MUST leave at least one sheep on the space on which the original stack was standing. When you are happy with the split, click the 'Validate' option at the top of the game screen. Play continues with each player splitting any one of their stacks. A stack is blocked when it is surrounded by opponents' pieces or the edge, and can no longer be split and moved. Strategy Tip: Watching out for your biggest herd is usually a sound strategy to start with. Watch out for chokepoints that can be easily closed off leaving you without enough room to spread the rest of your herd. Try not to block yourself in and count your sheep carefully ! '''Ending and Winning the Game''': When all your sheep are blocked, you no longer continue playing. The game ends when only one player can still split a herd. The winner is the player who succeeds in controlling the most pasture spaces. In the case of a tie, the winner is the player who has the largest number of adjacent pasture spaces occupied by their herd of sheep. 4989d695fbc09fd832d936cf88db3f08eb932ebb Gamehelpsplits 0 181 1330 2015-01-17T21:28:21Z Senatorhung 4176 Created page with "The object of the game is to be the player who occupies the most spaces on the pasture. '''Building the Pasture and Initial Placement''': Each player begins with 4 diamond-sh..." wikitext text/x-wiki The object of the game is to be the player who occupies the most spaces on the pasture. '''Building the Pasture and Initial Placement''': Each player begins with 4 diamond-shaped pasture tiles. The first player places one of their pasture tiles on the board. The other players place one of their pasture tiles in turn, with each new tile connecting to the existing pasture on at least one side. This continues until each player has placed all 4 of their pasture tiles. Then, again starting with the first player, each player places their entire stack of 16 sheep on any unoccupied pasture along the OUTSIDE border. Strategy Tip: Games can be won and lost in this phase ! The first player tends to start with an advantage as they have first placement AND first move. You may build the board differently depending on whether you are the first player or one of the subsequent players. In considering initial placement, think about who will act before you and what their likely first move will be. '''Playing the Game''': On your turn, your move consists of splitting a stack of your own sheep into two parts, moving part of the stack in a straight line as far as it can go before hitting another sheep or the border. Click on the stack you wish to split. Then, click on the desired destination pasture space. This will split your herd in two halves. Click on the original or destination space to adjust the amount of sheep you want in each herd. You MUST leave at least one sheep on the space on which the original stack was standing. When you are happy with the split, click the 'Validate' option at the top of the game screen. Play continues with each player splitting any one of their stacks. A stack is blocked when it is surrounded by opponents' pieces or the edge, and can no longer be split and moved. Strategy Tip: Watching out for your biggest herd is usually a sound strategy to start with. Watch out for chokepoints that can be easily closed off leaving you without enough room to spread the rest of your herd. Try not to block yourself in and count your sheep carefully ! '''Ending and Winning the Game''': When all your sheep are blocked, you no longer continue playing. The game ends when only one player can still split a herd. The winner is the player who succeeds in controlling the most pasture spaces. In the case of a tie, the winner is the player who has the largest number of adjacent pasture spaces occupied by their herd of sheep. 4989d695fbc09fd832d936cf88db3f08eb932ebb 1338 1330 2015-01-20T03:37:16Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to be the player who occupies the most spaces on the pasture. '''Building the Pasture and Initial Placement''': Each player begins with 4 diamond-shaped pasture tiles. The first player places one of their pasture tiles on the board. The other players place one of their pasture tiles in turn, with each new tile connecting to the existing pasture on at least one side. This continues until each player has placed all 4 of their pasture tiles. Then, again starting with the first player, each player places their entire stack of 16 sheep on any unoccupied pasture along the OUTSIDE border. Strategy Tip: Games can be won and lost in this phase ! The first player tends to start with an advantage as they have first placement AND first move. You may build the board differently depending on whether you are the first player or one of the subsequent players. In considering initial placement, think about who will act before you and what their likely first move will be. '''Playing the Game''': On your turn, your move consists of splitting a stack of your own sheep into two parts, moving part of the stack in a straight line as far as it can go before hitting another sheep or the border (sheep can not jump over other sheep or gaps). Click on the stack you wish to split. Then, click on the desired destination pasture space. This will split your herd in two halves. Click on the original or destination space to adjust the amount of sheep you want in each herd. You MUST leave at least one sheep on the space on which the original stack was standing. When you are happy with the split, click the 'Validate' option at the top of the game screen. Play continues with each player splitting any one of their stacks. A stack is blocked when it is surrounded by opponents' pieces or the edge, and can no longer be split and moved. Strategy Tip: Watching out for your biggest herd is usually a sound strategy to start with. Watch out for chokepoints that can be easily closed off leaving you without enough room to spread the rest of your herd. Try not to block yourself in and count your sheep carefully ! '''Ending and Winning the Game''': When all your sheep are blocked, you no longer continue playing. The game ends when only one player can still split a herd. The winner is the player who succeeds in controlling the most pasture spaces. In the case of a tie, the winner is the player who has the largest number of adjacent pasture spaces occupied by their herd of sheep. 651e6682437ba22937552f2f887ae030b61b7efa Gamehelpchinagold 0 136 1331 985 2015-01-17T22:02:47Z Senatorhung 4176 wikitext text/x-wiki A Tactical Dice Game by Günter Cornett for 2 players of 8 years and up (Original Translation: Ben Baldanza) '''What China Gold is about''': Both players search for gold, one in the mountains and the other in the rivers. If all gold of all prospecting areas of a mountain or a river is found, the mountain or river player can protect the find. But note that every prospecting area is at the same moment part of a mountain and part of a river. Thus the player that finds the gold first can block the other from the find. '''The Game Board''': 17 mountains, 17 rivers and 91 Prospecting Areas are shown on the game board. The mountains and rivers can be seen as mirror images of each other. The Prospecting Areas are represented both as mountains (brown planes) and as rivers (blue lines). '''Game Play''': On each turn, the sum of the random discs indicates how many Prospecting Area Markers may be turned face up. The Prospecting Area Markers to be turned MUST lie side by side in a straight line, without a gap or previously discovered lumps of gold in between. Instead of turning the thrown number of Prospecting Area Markers face up, the player may hide exactly one nugget again by turning one Prospecting Area Marker face down. When the last marker in one of the player's areas (mountain or river) is turned face up, all of the gold in this area can be claimed. If the last Prospecting Area Marker in one of the opponent's areas is turned face up at the same time, the opponent then clears the gold in this area. '''Small Disc Reduction''': Five not yet turned Prospecting Area Markers in a straight line make two different possibilities to turn four Prospecting Area Markers face up. When there is at most one straight line of five Prospecting Area Markers neighboring in straight line that could be turned face up, the small disc 0/1 is returned to the box. For the remainder of the game, small discs 0/2 and 1/2 will be used so that only numbers from 1 to 4 will be available. Four not yet turned Prospecting Area Markers in a straight line make two different possibilities to turn three Prospecting Area Markers face up. When there is at most one straight line of four Prospecting Area Markers neighboring in straight line that could be turned face up, the small disc 0/2 is replaced with the small disc 0/1 from the box so that only numbers from 1to 3 will be available. When there is at most one straight line of three Prospecting Area Markers neighboring in straight line that could be turned face up, all small discs are returned to the box. From now on the players may choose between turning a single or two neighbouring Prospecting Area Markers face up. If turning back a Prospecting Area Marker creates a situation with more possibilities to turn free Prospecting Area Markers in straight line face up, the appropriate number of small discs is used. '''Game End''': When all Prospecting Areas are cleared, the player who collected the most gold is the winner ! bbaf1cac39c8e275a5de8877c2d8ce74e2a6692b 1332 1331 2015-01-17T22:03:06Z Senatorhung 4176 wikitext text/x-wiki A Tactical Dice Game by Günter Cornett for 2 players of 8 years and up (Original Translation: Ben Baldanza) '''What China Gold is about''': Both players search for gold, one in the mountains and the other in the rivers. If all gold of all prospecting areas of a mountain or a river is found, the mountain or river player can protect the find. But note that every prospecting area is at the same moment part of a mountain and part of a river. Thus the player that finds the gold first can block the other from the find. '''The Game Board''': 17 mountains, 17 rivers and 91 Prospecting Areas are shown on the game board. The mountains and rivers can be seen as mirror images of each other. The Prospecting Areas are represented both as mountains (brown planes) and as rivers (blue lines). '''Game Play''': On each turn, the sum of the random discs indicates how many Prospecting Area Markers may be turned face up. The Prospecting Area Markers to be turned MUST lie side by side in a straight line, without a gap or previously discovered lumps of gold in between. Instead of turning the thrown number of Prospecting Area Markers face up, the player may hide exactly one nugget again by turning one Prospecting Area Marker face down. When the last marker in one of the player's areas (mountain or river) is turned face up, all of the gold in this area can be claimed. If the last Prospecting Area Marker in one of the opponent's areas is turned face up at the same time, the opponent then clears the gold in this area. '''Small Disc Reduction''': Five not yet turned Prospecting Area Markers in a straight line make two different possibilities to turn four Prospecting Area Markers face up. When there is at most one straight line of five Prospecting Area Markers neighboring in straight line that could be turned face up, the small disc 0/1 is returned to the box. For the remainder of the game, small discs 0/2 and 1/2 will be used so that only numbers from 1 to 4 will be available. Four not yet turned Prospecting Area Markers in a straight line make two different possibilities to turn three Prospecting Area Markers face up. When there is at most one straight line of four Prospecting Area Markers neighboring in straight line that could be turned face up, the small disc 0/2 is replaced with the small disc 0/1 from the box so that only numbers from 1to 3 will be available. When there is at most one straight line of three Prospecting Area Markers neighboring in straight line that could be turned face up, all small discs are returned to the box. From now on the players may choose between turning a single or two neighbouring Prospecting Area Markers face up. If turning back a Prospecting Area Marker creates a situation with more possibilities to turn free Prospecting Area Markers in straight line face up, the appropriate number of small discs is used. '''Game End''': When all Prospecting Areas are cleared, the player who collected the most gold is the winner ! 49c9a84b0d5719280ed0015a15f52243b9bb8bfd 1333 1332 2015-01-17T22:06:00Z Senatorhung 4176 wikitext text/x-wiki A Tactical Dice Game by Günter Cornett for 2 players of 8 years and up (Original Translation: Ben Baldanza) '''What China Gold is about''': Both players are searching for gold, one in the mountains and the other in the rivers. If all the gold of a prospecting area of a mountain or a river is found, the mountain or river player can claim the gold. But note that every prospecting area is at the same moment part of a mountain and part of a river. Thus the players are racing to see who can collect the gold first from each area. '''The Game Board''': 17 mountains, 17 rivers and 91 Prospecting Areas are shown on the game board. The Prospecting Areas are represented both as mountains (brown planes) and as rivers (blue lines). '''Game Play''': On each turn, the sum of the random discs indicates how many Prospecting Area Markers may be turned face up. The Prospecting Area Markers to be turned MUST lie side by side in a straight line, without a gap or previously discovered lumps of gold in between. Instead of turning the thrown number of Prospecting Area Markers face up, the player may hide exactly one nugget again by turning one Prospecting Area Marker face down. When the last marker in one of the player's areas (mountain or river) is turned face up, all of the gold in this area can be claimed. If the last Prospecting Area Marker in one of the opponent's areas is turned face up at the same time, the opponent then claims the gold in this area. '''Small Disc Reduction''': Five not yet turned Prospecting Area Markers in a straight line make two different possibilities to turn four Prospecting Area Markers face up. When there is at most one straight line of five Prospecting Area Markers neighboring in straight line that could be turned face up, the small disc 0/1 is returned to the box. For the remainder of the game, small discs 0/2 and 1/2 will be used so that only numbers from 1 to 4 will be available. Four not yet turned Prospecting Area Markers in a straight line make two different possibilities to turn three Prospecting Area Markers face up. When there is at most one straight line of four Prospecting Area Markers neighboring in straight line that could be turned face up, the small disc 0/2 is replaced with the small disc 0/1 from the box so that only numbers from 1to 3 will be available. When there is at most one straight line of three Prospecting Area Markers neighboring in straight line that could be turned face up, all small discs are returned to the box. From now on the players may choose between turning a single or two neighbouring Prospecting Area Markers face up. If turning back a Prospecting Area Marker creates a situation with more possibilities to turn free Prospecting Area Markers in straight line face up, the appropriate number of small discs is used. '''Game End''': When all Prospecting Areas are cleared, the player who collected the most gold is the winner ! 7d1e50477a826c3a29b48bee3793341f87fd4aeb Gamehelptournay 0 143 1334 1091 2015-01-17T22:40:27Z Senatorhung 4176 wikitext text/x-wiki Thanks to Mark Johnson (Eeeville) for his Tournay card descriptions used in the BGA adaptation! The '''game ends''' when both of the following conditions are met, or if condition 1 is met by more than one player: # A player has filled 9 spaces with at least 2 visible prestige buildings. # One Town Crier card more than the number of players has been revealed. The last round is triggered at the beginning of the start player's turn and each player gets a normal turn in this round. Then all players can choose a final card to play into their districts. ===Details of prestige buildings=== * You cannot score more than 12 victory points from the same prestige building. * If two players build the same prestige building there is only a single scoring. {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="110" | Prestige Building ! align="center" width="50" | Colour ! align="center" width="50" | Number Available ! align="center" width="50" | Cost to Play ! align="center" width="50" | Builder Points ! align="center" width="50" | Non-Builder Points ! align="center" | Condition |- | align="center" | '''Belfry''' | align="center" | Yellow | align="center" | 1 | align="center" | 5 deniers | align="center" | 4 | align="center" | 2 | align="center" | each set of visible buildings or characters<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''City Hall''' | align="center" | Yellow | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each yellow citizen owned |- | align="center" | '''Cloth Hall''' | align="center" | Yellow | align="center" | 2 | align="center" | 1 yellow citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible yellow building or character |- | align="center" | '''Mint''' | align="center" | Yellow | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each set of 4 deniers |- | align="center" | '''Tour des Six''' | align="center" | Yellow | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each visible character |- | align="center" | '''Cathedral''' | align="center" | White | align="center" | 1 | align="center" | 20 deniers | align="center" | 8 | align="center" | 0 | align="center" | none |- | align="center" | '''La Madeleine''' | align="center" | White | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each visible prestige building |- | align="center" | '''Saint-Brice''' | align="center" | White | align="center" | 1 | align="center" | 5 deniers | align="center" | 4 | align="center" | 2 | align="center" | each set of visible buildings or characters<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Saint-Jacques''' | align="center" | White | align="center" | 2 | align="center" | 1 white citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible white building or character |- | align="center" | '''Saint-Nicolas''' | align="center" | White | align="center" | 1 | align="center" | 5 deniers | align="center" | 3 | align="center" | 1 | align="center" | each set of citizens you own<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Saint-Quentin''' | align="center" | White | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each white citizen owned |- | align="center" | '''Pont des Trous''' | align="center" | Red | align="center" | 1 | align="center" | 5 deniers | align="center" | 3 | align="center" | 1 | align="center" | each set of citizens you own<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Porte de la Vigne''' | align="center" | Red | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each red citizen owned |- | align="center" | '''Tour d’Arras''' | align="center" | Red | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each visible white and yellow building |- | align="center" | '''Tour Henry VIII''' | align="center" | Red | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each rampart card built |- | align="center" | '''Tour Saint-Georges''' | align="center" | Red | align="center" | 2 | align="center" | 1 red citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible red building or character |} d0c577b4f3c022876ba2b7651569e47594f88d05 1335 1334 2015-01-17T22:42:49Z Senatorhung 4176 /* Details of prestige buildings */ wikitext text/x-wiki Thanks to Mark Johnson (Eeeville) for his Tournay card descriptions used in the BGA adaptation! The '''game ends''' when both of the following conditions are met, or if condition 1 is met by more than one player: # A player has filled 9 spaces with at least 2 visible prestige buildings. # One Town Crier card more than the number of players has been revealed. The last round is triggered at the beginning of the start player's turn and each player gets a normal turn in this round. Then all players can choose a final card to play into their districts. ===Details of prestige buildings=== * You cannot score more than 12 victory points from the same prestige building. * If two players build the same prestige building there is only a single scoring. '''Yellow:''' *'''Belfry''': per set (1 yellow + 1 white + 1 red) of buildings or characters *'''City Hall''': per yellow citizen (2x) *'''Cloth Hall''': per yellow building or character (2x) *'''Mint''': per set of 4 deniers (2x) *'''Tour des Six''': per character (2x) '''White:''' *'''Cathedral''': only the player who builds it earns 8 PPs. *'''La Madeleine''': per prestige building (2x) *'''Saint-Brice''': per set (1 yellow + 1 white + 1 red) of buildings or characters *'''Saint-Jacques''': per white building or character (2x) *'''Saint-Nicolas''': per set of citizens you own (1 yellow +1 white +1 red) *'''Saint-Quentin''': per white citizen (2x) '''Red:''' *'''Pont des Trous''': per set (1 yellow + 1 white + 1 red) of citizens *'''Porte de la Vigne''': per red citizen (2x) *'''Tour d’Arras''': per white and yellow building (2x) *'''Tour Henry VIII''': per rampart built (2x) *'''Tour Saint-Georges''': per red card building or character (2x) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="110" | Prestige Building ! align="center" width="50" | Colour ! align="center" width="50" | Number Available ! align="center" width="50" | Cost to Play ! align="center" width="50" | Builder Points ! align="center" width="50" | Non-Builder Points ! align="center" | Condition |- | align="center" | '''Belfry''' | align="center" | Yellow | align="center" | 1 | align="center" | 5 deniers | align="center" | 4 | align="center" | 2 | align="center" | each set of visible buildings or characters<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''City Hall''' | align="center" | Yellow | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each yellow citizen owned |- | align="center" | '''Cloth Hall''' | align="center" | Yellow | align="center" | 2 | align="center" | 1 yellow citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible yellow building or character |- | align="center" | '''Mint''' | align="center" | Yellow | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each set of 4 deniers |- | align="center" | '''Tour des Six''' | align="center" | Yellow | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each visible character |- | align="center" | '''Cathedral''' | align="center" | White | align="center" | 1 | align="center" | 20 deniers | align="center" | 8 | align="center" | 0 | align="center" | none |- | align="center" | '''La Madeleine''' | align="center" | White | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each visible prestige building |- | align="center" | '''Saint-Brice''' | align="center" | White | align="center" | 1 | align="center" | 5 deniers | align="center" | 4 | align="center" | 2 | align="center" | each set of visible buildings or characters<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Saint-Jacques''' | align="center" | White | align="center" | 2 | align="center" | 1 white citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible white building or character |- | align="center" | '''Saint-Nicolas''' | align="center" | White | align="center" | 1 | align="center" | 5 deniers | align="center" | 3 | align="center" | 1 | align="center" | each set of citizens you own<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Saint-Quentin''' | align="center" | White | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each white citizen owned |- | align="center" | '''Pont des Trous''' | align="center" | Red | align="center" | 1 | align="center" | 5 deniers | align="center" | 3 | align="center" | 1 | align="center" | each set of citizens you own<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Porte de la Vigne''' | align="center" | Red | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each red citizen owned |- | align="center" | '''Tour d’Arras''' | align="center" | Red | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each visible white and yellow building |- | align="center" | '''Tour Henry VIII''' | align="center" | Red | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each rampart card built |- | align="center" | '''Tour Saint-Georges''' | align="center" | Red | align="center" | 2 | align="center" | 1 red citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible red building or character |} 587636ef0a81c4dff977a462c2bf210d6bd419f9 Help 0 4 1337 1285 2015-01-18T00:35:59Z Squarerootofthree 5668 /* Games */ wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] could probably help you. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcheckers|Checkers]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpeightmastersrevenge|8 Master's Revenge]] * [[Gamehelpelfenland|Elfenland]] </td> <td valign="top"> * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpinjawara|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] </td> <td valign="top"> * [[Gamehelpkoryo|Koryŏ]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsechsnimmt|6 Nimmt!]] </td> <td valign="top"> * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelpsechsnimmt|Take 5!]] * [[Gamehelptashkalar|Tash-Kalar]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] </td> <td valign="top"> * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> 7cf8dc1789c144e740f86e2181b730e7904afe4e Gamehelpkoryo 0 182 1339 2015-01-20T23:30:19Z Roguem 7648 Created page with "THE OMNISCIENT (1 unique card in play – Value of 1 unique Influence Point): The power of the « Omniscient » is permanent. In case of a tie for the majority on any given fa..." wikitext text/x-wiki THE OMNISCIENT (1 unique card in play – Value of 1 unique Influence Point): The power of the « Omniscient » is permanent. In case of a tie for the majority on any given family, the player controlling the « Omniscient » wins the tie and may use the corresponding power. So, if 3 players have 2 « Guardians » in play, but one also controls the « Omniscient », then he is the one protected from the « Barbarian » event. Not the others. 48116c743d9050bae96d8becebf9a371080c16d7 1340 1339 2015-01-20T23:36:14Z Roguem 7648 wikitext text/x-wiki THE OMNISCIENT (1 unique card in play – Value of 1 unique Influence Point): The power of the « Omniscient » is permanent. In case of a tie for the majority on any given family, the player controlling the « Omniscient » wins the tie and may use the corresponding power. So, if 3 players have 2 « Guardians » in play, but one also controls the « Omniscient », then he is the one protected from the « Barbarian » event. Not the others. This power does not break ties for scoring Influence Points during the final scoring phase. It is applicable only during the rounds. 9e9cce1a316ef280f84bcfabe71f029b273a3197 1341 1340 2015-01-21T01:17:38Z Roguem 7648 wikitext text/x-wiki THE OMNISCIENT (1): In case of a tie for majority the player controlling this character wins the tie and may use the corresponding power. This power does not break ties during the final scoring. (2) (3) (4) (5) (6) GUARDIAN (7): As long as a player has the majority associated with this character, he may not be the target of a « Barbarian » event. (8) (9) 72ab2b393ea3692c0364ef0ec5eeddcbd04be7d5 1342 1341 2015-01-21T01:19:36Z Roguem 7648 wikitext text/x-wiki THE OMNISCIENT (1): In case of a tie for majority the player controlling this character wins the tie and may use the corresponding power. This power does not break ties during the final scoring. (2) (3) PRIEST (4): During his turn, if a player has the majority associated with this character he may destroy one of his « Event » cards. (5) (6) GUARDIAN (7): As long as a player has the majority associated with this character, he may not be the target of a « Barbarian » event. (8) (9) d880ffea9520eeb28a4e5e2c543588bc31c6ea15 1343 1342 2015-01-21T01:24:08Z Roguem 7648 wikitext text/x-wiki THE OMNISCIENT (1): In case of a tie for majority the player controlling this character wins the tie and may use the corresponding power. This power does not break ties during the final scoring. (2) (3) PRIEST (4): During his turn, if a player has the majority associated with this character he may destroy one of his « Event » cards. SHIP OWNER (5) During the Order Phase, if a player has the majority associated with this character he may play 1 card each of 2 different types instead of playing only cards of the same type. (6) GUARDIAN (7): As long as a player has the majority associated with this character, he may not be the target of a « Barbarian » event. (8) (9) 9bb5c283c1e6c467f5235ecef048305f27923d14 1344 1343 2015-01-21T01:31:06Z Roguem 7648 wikitext text/x-wiki THE OMNISCIENT (1): In case of a tie for majority the player controlling this character wins the tie and may use the corresponding power. This power does not break ties during the final scoring. (2) (3) PRIEST (4): During his turn, if a player has the majority associated with this character he may destroy one of his « Event » cards. SHIP OWNER (5) During the Order Phase, if a player has the majority associated with this character he may play 1 card each of 2 different types instead of playing only cards of the same type. BANKER (6): If a player has the majority associated with this character he may take Money token. When the Bank is empty this power becomes ineffective. GUARDIAN (7): As long as a player has the majority associated with this character, he may not be the target of a « Barbarian » event. (8) (9) 6086797a979164e8446b2f4ab00eef4f82293a85 1345 1344 2015-01-21T01:34:28Z Roguem 7648 wikitext text/x-wiki THE OMNISCIENT (1): In case of a tie for majority the player controlling this character wins the tie and may use the corresponding power. This power does not break ties during the final scoring. (2) (3) PRIEST (4): During his turn, if a player has the majority associated with this character he may destroy one of his « Event » cards. SHIP OWNER (5) During the Order Phase, if a player has the majority associated with this character he may play 1 card each of 2 different types instead of playing only cards of the same type. BANKER (6): If a player has the majority associated with this character he may take a Money token. When the Bank is empty this power becomes ineffective. GUARDIAN (7): As long as a player has the majority associated with this character, he may not be the target of a « Barbarian » event. BROADCASTER (8): During the Card Distribution Phase, if a player has the majority associated with this character may get one card more than the number allowed for the active season. (9) 96ac99b53b53d6f5431c34b0e80922780241936e 1346 1345 2015-01-21T01:38:10Z Roguem 7648 wikitext text/x-wiki THE OMNISCIENT (1): In case of a tie for majority the player controlling this character wins the tie and may use the corresponding power. This power does not break ties during the final scoring. (2) (3) PRIEST (4): During his turn, if a player has the majority associated with this character he may destroy one of his « Event » cards. SHIP OWNER (5) During the Order Phase, if a player has the majority associated with this character he may play 1 card each of 2 different types instead of playing only cards of the same type. BANKER (6): If a player has the majority associated with this character he may take a Money token. When the Bank is empty this power becomes ineffective. GUARDIAN (7): As long as a player has the majority associated with this character, he may not be the target of a « Barbarian » event. BROADCASTER (8): During the Card Distribution Phase, if a player has the majority associated with this character may get one card more than the number allowed for the active season. MERCHANT (9): This character has no special power other than awarding the player with the majority associated with this character 9 Influence points at the end of the game. 482034c2f57bd83746aa3c016e944579a0aa4751 1347 1346 2015-01-21T01:45:20Z Roguem 7648 wikitext text/x-wiki THE OMNISCIENT (1): In case of a tie for majority, the player controlling this character wins the tie and may use the corresponding power. This power does not break ties during final scoring. SENATOR (2): During the Ending Phase, the player who has the majority associated with this character may keep 2 cards more than the number allowed for the active season. (3) PRIEST (4): During his turn, the player who has the majority associated with this character may destroy one of his Event cards. SHIP OWNER (5) During the Order Phase, the player who has the majority associated with this character may play 1 card each of 2 different types instead of playing only cards of the same type. BANKER (6): The player who has the majority associated with this character may take a Money token. When the Bank is empty this power becomes inactive. GUARDIAN (7): As long as a player has the majority associated with this character, he may not be the target of a Barbarian event. BROADCASTER (8): During the Card Distribution Phase, the player who has the majority associated with this character may get one card more than the number allowed for the active season. MERCHANT (9): This character has no special power other than awarding the player with the majority associated with this character 9 Influence points at the end of the game. 870f21db28608fb4fbf3383735e03a9169ef43d2 1348 1347 2015-01-21T10:56:04Z Roguem 7648 wikitext text/x-wiki THE OMNISCIENT (1): In case of a tie for majority, the player controlling this character wins the tie and may use the corresponding power. This power does not break ties during final scoring. SPY (2): This character has two powers, each requiring conditions to be met. A - During his turn, the player who has the majority associated with this character may steal a Money token from another player; B - As long as he has no Guardian in play, the player who has the majority associated with this character may not be targeted by any Lobbying event, even if he is the one playing it (he must choose other players to swap cards, hence this power is not available in 2 player games). SENATOR (3): During the Ending Phase, the player who has the majority associated with this character may keep 2 cards more than the number allowed for the active season. PRIEST (4): During his turn, the player who has the majority associated with this character may destroy one of his Event cards. SHIP OWNER (5) During the Order Phase, the player who has the majority associated with this character may play 1 card each of 2 different types instead of playing only cards of the same type. BANKER (6): The player who has the majority associated with this character may take a Money token. When the Bank is empty this power becomes inactive. GUARDIAN (7): As long as a player has the majority associated with this character, he may not be the target of a Barbarian event. BROADCASTER (8): During the Card Distribution Phase, the player who has the majority associated with this character may get one card more than the number allowed for the active season. MERCHANT (9): This character has no special power other than awarding the player with the majority associated with this character 9 Influence points at the end of the game. d862f77dfdad20171af33714967d33a936f87f29 1349 1348 2015-01-21T10:56:59Z Roguem 7648 wikitext text/x-wiki THE OMNISCIENT (1): In case of a tie for majority, the player controlling this character wins the tie and may use the corresponding power. This power does not break ties during final scoring. SPY (2): This character has two powers, each requiring specific conditions to be met. A - During his turn, the player who has the majority associated with this character may steal a Money token from another player; B - As long as he has no Guardian in play, the player who has the majority associated with this character may not be targeted by any Lobbying event, even if he is the one playing it (he must choose other players to swap cards, hence this power is not available in 2 player games). SENATOR (3): During the Ending Phase, the player who has the majority associated with this character may keep 2 cards more than the number allowed for the active season. PRIEST (4): During his turn, the player who has the majority associated with this character may destroy one of his Event cards. SHIP OWNER (5) During the Order Phase, the player who has the majority associated with this character may play 1 card each of 2 different types instead of playing only cards of the same type. BANKER (6): The player who has the majority associated with this character may take a Money token. When the Bank is empty this power becomes inactive. GUARDIAN (7): As long as a player has the majority associated with this character, he may not be the target of a Barbarian event. BROADCASTER (8): During the Card Distribution Phase, the player who has the majority associated with this character may get one card more than the number allowed for the active season. MERCHANT (9): This character has no special power other than awarding the player with the majority associated with this character 9 Influence points at the end of the game. 1b8c25bebaf31439ce302aca972b222d3c2701a1 1350 1349 2015-01-21T20:39:08Z Roguem 7648 wikitext text/x-wiki BARBARIANS (-1): Thee player who plays this event may destroy a character in an opponent's tableau. The player who has the majority of Guardians may not be targeted. THE OMNISCIENT (1): In case of a tie for majority, the player controlling this character wins the tie and may use the corresponding power. This power does not break ties during final scoring. SPY (2): This character has two powers, each requiring specific conditions to be met. A - During his turn, the player who has the majority associated with this character may steal a Money token from another player; B - As long as he has no Guardian in play, the player who has the majority associated with this character may not be targeted by any Lobbying event, even if he is the one playing it (he must choose other players to swap cards, hence this power is not available in 2 player games). SENATOR (3): During the Ending Phase, the player who has the majority associated with this character may keep 2 cards more than the number allowed for the active season. PRIEST (4): During his turn, the player who has the majority associated with this character may destroy one of his Event cards. SHIP OWNER (5) During the Order Phase, the player who has the majority associated with this character may play 1 card each of 2 different types instead of playing only cards of the same type. BANKER (6): The player who has the majority associated with this character may take a Money token. When the Bank is empty this power becomes inactive. GUARDIAN (7): As long as a player has the majority associated with this character, he may not be the target of a Barbarian event. BROADCASTER (8): During the Card Distribution Phase, the player who has the majority associated with this character may get one card more than the number allowed for the active season. MERCHANT (9): This character has no special power other than awarding the player with the majority associated with this character 9 Influence points at the end of the game. ee24f0b4a290c92b2cda962702a7919e2e732341 1351 1350 2015-01-21T20:43:35Z Roguem 7648 wikitext text/x-wiki THE OMNISCIENT (1): In case of a tie for majority, the player controlling this character wins the tie and may use the corresponding power. This power does not break ties during final scoring. SPY (2): This character has two powers, each requiring specific conditions to be met. A - During his turn, the player who has the majority associated with this character may steal a Money token from another player; B - As long as he has no Guardian in play, the player who has the majority associated with this character may not be targeted by any Lobbying event, even if he is the one playing it (he must choose other players to swap cards, hence this power is not available in 2 player games). SENATOR (3): During the Ending Phase, the player who has the majority associated with this character may keep 2 cards more than the number allowed for the active season. PRIEST (4): During his turn, the player who has the majority associated with this character may destroy one of his Event cards. SHIP OWNER (5) During the Order Phase, the player who has the majority associated with this character may play 1 card each of 2 different types instead of playing only cards of the same type. BANKER (6): The player who has the majority associated with this character may take a Money token. When the Bank is empty this power becomes inactive. GUARDIAN (7): As long as a player has the majority associated with this character, he may not be the target of a Barbarian event. BROADCASTER (8): During the Card Distribution Phase, the player who has the majority associated with this character may get one card more than the number allowed for the active season. MERCHANT (9): This character has no special power other than awarding the player with the majority associated with this character 9 Influence points at the end of the game. BARBARIANS (-1): The player who plays this event may destroy a character card in an opponent's tableau. The player who has the majority of Guardians may not be targeted. LOBBYING (-1): The player who plays this event may swap 2 character cards between two different players. The player who has the majority of Spies may not be targeted (including the player playing the event). d2fb83810fb7a88066ad774a6846c02752a4ad77 Gamehelpgyges 0 183 1352 2015-01-23T00:20:40Z Squarerootofthree 5668 Created page with "Gyges '''Introduction''' The board game has 6x6 spaces on which pieces can move. A player wins when he can put a piece on his opponent's goal. '''The pieces''' There are 4..." wikitext text/x-wiki Gyges '''Introduction''' The board game has 6x6 spaces on which pieces can move. A player wins when he can put a piece on his opponent's goal. '''The pieces''' There are 4 pieces of each type, the simple rings (1 move), the double rings (2 moves) and the triple rings (3 moves). All of the pieces have the same color, and a player can only move a piece if this one is on the first non-empty row. '''Starting Positions''' Players choose their starting arrangement on their first row. Each one has 2 pieces of each type. The first player (South) puts his pieces on its first row. Then the second player does the same. And the game starts: each player moves a (one) piece in a turn. '''Move of a Piece''' A piece moves of as many spaces (neither more nor less) than it has rings. A piece moves from space to space orthogonally and spaces must be empty (a piece cannot pace through another piece). All four directions are allowed, but moving diagonal is forbidden. When the last move of a piece reaches an occupied space, the player has two choices: '''Bounce''' or '''Replace''' '''Bounce:''' The piece bounces on the reached piece of as many moves as this piece has rings. A piece can bounce off several pieces. Beware: when a piece bounces on a triple, for example, you must make 2 moves before bouncing again. '''Replace:''' When a piece lands on an occupied space you may leave it there and move the landed on piece to any free space on the board, except behind the opponent's first line. A piece can move, bounce one or more times, and finish his move on an occupied space and replace it. The move of a piece can sometimes be long and complex, but it is often the only way to reach the goal: Put a piece on the opponent's goal! '''Forbidden moves''' * A piece, during his move, can only pass through a space one time. * A piece can't pass through a goal. He can only reach it. * A piece can't pass through another piece. * To win, a piece must finish his move exactly on the goal. * A replaced piece can't be put beyond the opponent's first line. 395bd4517cd4bf283701b45aad62c87a07d510f7 Gamehelptournay 0 143 1353 1335 2015-01-26T08:44:04Z Senatorhung 4176 wikitext text/x-wiki Thanks to Mark Johnson (Eeeville) for his Tournay card descriptions used in the BGA adaptation! The '''game ends''' when both of the following conditions are met, or if condition 1 is met by more than one player:<BR> <OL><LI>A player has filled 9 spaces with at least 2 visible prestige buildings.</LI> <LI> One Town Crier card more than the number of players has been revealed.</LI></OL> The last round is triggered at the beginning of the start player's turn and each player gets a normal turn in this round. Then all players can choose a final card to play into their districts. ===Details of prestige buildings=== * You cannot score more than 12 victory points from the same prestige building. * If two players build the same prestige building there is only a single scoring. '''Yellow:''' *'''Belfry''': per set (1 yellow + 1 white + 1 red) of buildings or characters *'''City Hall''': per yellow citizen (2x) *'''Cloth Hall''': per yellow building or character (2x) *'''Mint''': per set of 4 deniers (2x) *'''Tour des Six''': per character (2x) '''White:''' *'''Cathedral''': only the player who builds it earns 8 PPs. *'''La Madeleine''': per prestige building (2x) *'''Saint-Brice''': per set (1 yellow + 1 white + 1 red) of buildings or characters *'''Saint-Jacques''': per white building or character (2x) *'''Saint-Nicolas''': per set of citizens you own (1 yellow +1 white +1 red) *'''Saint-Quentin''': per white citizen (2x) '''Red:''' *'''Pont des Trous''': per set (1 yellow + 1 white + 1 red) of citizens *'''Porte de la Vigne''': per red citizen (2x) *'''Tour d’Arras''': per white and yellow building (2x) *'''Tour Henry VIII''': per rampart built (2x) *'''Tour Saint-Georges''': per red card building or character (2x) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="110" | Prestige Building ! align="center" width="50" | Colour ! align="center" width="50" | Number Available ! align="center" width="50" | Cost to Play ! align="center" width="50" | Builder Points ! align="center" width="50" | Non-Builder Points ! align="center" | Condition |- | align="center" | '''Belfry''' | align="center" | Yellow | align="center" | 1 | align="center" | 5 deniers | align="center" | 4 | align="center" | 2 | align="center" | each set of visible buildings or characters<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''City Hall''' | align="center" | Yellow | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each yellow citizen owned |- | align="center" | '''Cloth Hall''' | align="center" | Yellow | align="center" | 2 | align="center" | 1 yellow citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible yellow building or character |- | align="center" | '''Mint''' | align="center" | Yellow | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each set of 4 deniers |- | align="center" | '''Tour des Six''' | align="center" | Yellow | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each visible character |- | align="center" | '''Cathedral''' | align="center" | White | align="center" | 1 | align="center" | 20 deniers | align="center" | 8 | align="center" | 0 | align="center" | none |- | align="center" | '''La Madeleine''' | align="center" | White | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each visible prestige building |- | align="center" | '''Saint-Brice''' | align="center" | White | align="center" | 1 | align="center" | 5 deniers | align="center" | 4 | align="center" | 2 | align="center" | each set of visible buildings or characters<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Saint-Jacques''' | align="center" | White | align="center" | 2 | align="center" | 1 white citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible white building or character |- | align="center" | '''Saint-Nicolas''' | align="center" | White | align="center" | 1 | align="center" | 5 deniers | align="center" | 3 | align="center" | 1 | align="center" | each set of citizens you own<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Saint-Quentin''' | align="center" | White | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each white citizen owned |- | align="center" | '''Pont des Trous''' | align="center" | Red | align="center" | 1 | align="center" | 5 deniers | align="center" | 3 | align="center" | 1 | align="center" | each set of citizens you own<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Porte de la Vigne''' | align="center" | Red | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each red citizen owned |- | align="center" | '''Tour d’Arras''' | align="center" | Red | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each visible white and yellow building |- | align="center" | '''Tour Henry VIII''' | align="center" | Red | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each rampart card built |- | align="center" | '''Tour Saint-Georges''' | align="center" | Red | align="center" | 2 | align="center" | 1 red citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible red building or character |} 5f2bcdf7ca5afc2ae9497c88e1d165a2c09eb772 Gamehelpk2 0 184 1354 2015-01-28T15:10:26Z Squarerootofthree 5668 Created page with "'''Turn Summary''' <ol> <li>'''Card Selection'''</li> <ol> <li>Each player plays 3 cards face down.</li> <li>Players reveal them simultan..." wikitext text/x-wiki '''Turn Summary''' <ol> <li>'''Card Selection'''</li> <ol> <li>Each player plays 3 cards face down.</li> <li>Players reveal them simultaneously.</li> </ol> <li>'''Risk Tokens'''</li> <ol> <li>The player with the most movement points takes a risk token. In case of a tie, no one takes a risk token.</li> <li>Another risk token is revealed if needed.</li> </ol> <li>'''Action Phase'''</li> <ol> <li>Players move their climbers using their played (green) cards.</li> <li>Placing a tent costs the same as the cost to enter that space.</li> <li>Players increase their climbers' acclimatization level using their played (blue) cards.</li> <li>The player with a risk token must suffer the consequences and reduce their movement by that amount.</li> <li>Each climber's newly gained victory points are marked on the victory point track.</li> <li>Note the influence of weather on movement (only in winter weather)!.</li> </ol> <li>'''Acclimatization Checks'''</li> <ol> <li>Add/subtract acclimatization according to each climber's current space.</li> <li>A tent adds +1 to acclimatization.</li> <li>Subtract acclimatization resulting from the current weather, if in the affected altitude zone.</li> <li>If acclimatization exceeds 6, it is reduced back to 6.</li> <li>If acclimatization drops below 1, the climber dies and losing any VP gained.</li> </ol> <li>'''End of Turn'''</li> <ol> <li>The starting player marker passes to the left.</li> <li>The weather marker moves to the next space.</li> <li>Draw 3 cards to have 6 again.</li> </ol> </ol> d142b0e679a3245e99227086699f32184879a3c6 1372 1354 2015-02-15T22:47:00Z Roguem 7648 wikitext text/x-wiki '''Turn Summary''' <ol> <li>'''Card Selection'''</li> <ol> <li>Each player plays 3 cards face down.</li> <li>Players reveal them simultaneously.</li> </ol> <li>'''Risk Tokens'''</li> <ol> <li>The player with the most movement points takes a risk token. In case of a tie, no one takes a risk token.</li> <li>Another risk token is revealed if needed.</li> </ol> <li>'''Action Phase'''</li> <ol> <li>Players move their climbers using their played (green) cards.</li> <li>Placing a tent costs the same as the cost to enter that space.</li> <li>Players increase their climbers' acclimatization level using their played (blue) cards.</li> <li>The player with a risk token must suffer the consequences and either reduce their movement by that amount or, if they choose not to, subtract acclimatization points from a climber who had one or more cards assigned to this turn.</li> <li>Each climber's newly gained victory points are marked on the victory point track.</li> <li>Note the influence of weather on movement (only in winter weather)!.</li> </ol> <li>'''Acclimatization Checks'''</li> <ol> <li>Add/subtract acclimatization according to each climber's current space.</li> <li>A tent adds +1 to acclimatization.</li> <li>Subtract acclimatization resulting from the current weather, if in the affected altitude zone.</li> <li>If acclimatization exceeds 6, it is reduced back to 6.</li> <li>If acclimatization drops below 1, the climber dies and losing any VP gained.</li> </ol> <li>'''End of Turn'''</li> <ol> <li>The starting player marker passes to the left.</li> <li>The weather marker moves to the next space.</li> <li>Draw 3 cards to have 6 again.</li> </ol> </ol> 5a59321c7a86312580697f80f347f4ef34ea7dd3 1391 1372 2015-03-10T11:39:39Z Oscarfg 8023 wikitext text/x-wiki '''Resumen del turno''' <ol> <li>'''Selección de cartas'''</li> <ol> <li>Cada jugador coloca 3 cartas de su mano boca abajo.</li> <li>Los jugadores las revelan simultaneamente.</li> </ol> <li>'''Fichas de riesgo'''</li> <ol> <li>El jugador con más puntos de movimiento toma una ficha de riesgo. En caso de empate nadie toma una ficha de riesgo.</li> <li>Se revela otra ficha de riesgo si fuera necesario.</li> </ol> <li>'''Fase de Acción'''</li> <ol> <li>Los jugadores mueven a sus montañeros usando sus cartas jugadas (verdes).</li> <li>Montar una tienda cuesta lo mismo que el coste de entrar en ese espacio.</li> <li>Los jugadores pueden subir el nivel de aclimatación de sus montañeros usando sus cartas jugadas (azules).</li> <li>El jugador con la ficha de riesgo debe sufrir las consecuencias y, o bien reducir su movimiento en esa cantidad o, si elige no hacerlo, restar los puntos de un montañero que tuviera una o más cartas asignadas en ese turno.</li> <li>Los puntos de victoria ganados por cada montañero se asignan en el marcador de puntos de victoria.</li> <li>Hay que tener en cuenta la influencia del clima al moverse (solo con tiempo invernal).</li> </ol> <li>'''Comprobación de aclimatación'''</li> <ol> <li>Suma/resta la aclimatación en función de cada montañero en ese mismo espacio.</li> <li>Una tienda añade +1 a la aclimatación.</li> <li>Resta la aclimatación debida al clima actual, si afecta a la a altitud de la zona.</li> <li>Si la aclimatación es mayor de 6, queda reducida a 6.</li> <li>Si la aclimatación baja de 1, el montañero muere y pierte los puntos de victoria obtenidos.</li> </ol> <li>'''Fin del turno'''</li> <ol> <li>El jugador incial pasa el marcador al jugador de su izquierda.</li> <li>El marcador de clima se mueve al siguiente espacio.</li> <li>Robar 3 cartas para tener nuevamente 6.</li> </ol> </ol> 673c931d4d170d6dc2a344bd7082f9d51e4bbde5 1397 1391 2015-03-21T18:24:32Z Squarerootofthree 5668 Undo revision 1391 by [[Special:Contributions/Oscarfg|Oscarfg]] ([[User talk:Oscarfg|talk]]) wikitext text/x-wiki '''Turn Summary''' <ol> <li>'''Card Selection'''</li> <ol> <li>Each player plays 3 cards face down.</li> <li>Players reveal them simultaneously.</li> </ol> <li>'''Risk Tokens'''</li> <ol> <li>The player with the most movement points takes a risk token. In case of a tie, no one takes a risk token.</li> <li>Another risk token is revealed if needed.</li> </ol> <li>'''Action Phase'''</li> <ol> <li>Players move their climbers using their played (green) cards.</li> <li>Placing a tent costs the same as the cost to enter that space.</li> <li>Players increase their climbers' acclimatization level using their played (blue) cards.</li> <li>The player with a risk token must suffer the consequences and either reduce their movement by that amount or, if they choose not to, subtract acclimatization points from a climber who had one or more cards assigned to this turn.</li> <li>Each climber's newly gained victory points are marked on the victory point track.</li> <li>Note the influence of weather on movement (only in winter weather)!.</li> </ol> <li>'''Acclimatization Checks'''</li> <ol> <li>Add/subtract acclimatization according to each climber's current space.</li> <li>A tent adds +1 to acclimatization.</li> <li>Subtract acclimatization resulting from the current weather, if in the affected altitude zone.</li> <li>If acclimatization exceeds 6, it is reduced back to 6.</li> <li>If acclimatization drops below 1, the climber dies and losing any VP gained.</li> </ol> <li>'''End of Turn'''</li> <ol> <li>The starting player marker passes to the left.</li> <li>The weather marker moves to the next space.</li> <li>Draw 3 cards to have 6 again.</li> </ol> </ol> 5a59321c7a86312580697f80f347f4ef34ea7dd3 Faq 0 3 1355 1245 2015-01-29T13:31:13Z Sourisdudesert 1 /* I launched a new table but nobody is joining? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he has run out of time on the game clock for the current move (red bar) or if he goes over his allotted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. ccfb0f03e0b392b585ed06364b08669e92d37fdb 1356 1355 2015-01-29T13:32:43Z Sourisdudesert 1 /* I joined a game. When does the game start? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can expel him from the game as soon as he has run out of time on the game clock for the current move (red bar) or if he goes over his allotted time to think by more than 3/4/5 minutes (depending on game speed). See Clock section for details. Important: in this case, no ELO points will be won by anybody for this game. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. f2c947b3794efc25cd9f0f84f491d198e532beaa 1357 1356 2015-01-29T13:37:10Z Sourisdudesert 1 /* A player has to make a move but he/she doesn't. What can I do? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://forum.boardgamearena.com/viewforum.php?f=4 bug section in the forum], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. His turn will be skipped until he gets back, and if he doesn't get back he will get a "leave" penalty. In this case you have two options: ** Continue the game until the end. This is recommended. This way you can win some ELO points. ** Abandon the game. Players out of time will automatically accept to abandon the game. In this case you won't win any ELO points (but the player who left the game will lose some). ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. 8c24e4193dc8a9c1fe19f5d91e4be0c3f8b295ab Game clock 0 15 1358 1126 2015-01-29T14:48:19Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] On '''Board Game Arena''' you are playing "live" (real time) or "turn-based" (asynchronously). In both cases, have an allotted delay to play your moves. Most of the time, your initial delay at the beginning of a game is some minutes (in realtime mode) or some days (in turn-based mode). During each turn, or on specific occasions, you get an additional delay. If you have no more time to play, you will get a "clock" penalty and your opponents can decide to skip your turns. == Time to think == Your allotted time to think is displayed on the right of your player's name. When it's your turn to play, this time is also displayed at the top of the web page. == Game speed == Table administrator can make a choice between some game speed profile (example: fast, normal, slow). There are many speeds for each mode (realtime and turn-based). The additional amount of time credited each turn depends on chosen game speed profile. Be careful to check game speed before game start to adapt your timing. The interface displays an estimation of the game duration based on recently played game with the same game and speed. Note: your allotted time to think cannot go higher that your initial time to think. For example, if you start the game with 5 minutes of thinking time, you time will be limited to 5 minutes maximum. Note: playing without time limit is strongly discouraged, except if you are playing with friends or to discover a new game. Remember that without time limit, you can't skip the turn of a player that is not playing. == Running out of time == As soon as you run out of time (negative clock), you get a clock penalty. '''For realtime games''': When a player has a negative clock, his opponents may make him skip his turn. Once this has been done, all following turns are skipped automatically. When you are in this situation (turns skipped automatically), you can get back in the game by clicking on the dedicated button "get back in this game". Note that you are not allowed to get back in the game if your clock is still negative. However, as all your turn are skipped, it shouldn't take long before your clock become positive again. If you can't/don't manage to get back in the game before the game end, you will get a "leave" penalty on your profile. '''For turn-based games''': On turn-based games, you are warned by email when you are running out of time. As soon as you are out of time, your next turn is skipped. == Continue the game after a "skip turn" == If you are playing in a game where a player skip all his turn, you have 2 options: * You can continue to play the game until the end. This is recommended. In this case you will win ELO points you deserve for your victory. * You can abandon the game. All players with a negative clock will accept automatically. In this case, players who leaved the game get an ELO penalty (in addition to a "leave" penalty). == "My opponent is too slow" == Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his allotted time to think. If you want to play fast, set up or join table with "fast" mode only, but don't force an opponent to play when he has the right to do so. == "I would like to think a little" == If you are in a critical step of the game and want to take some time to think, you can click on the link "I would like to think a little" on the top right of the page. Thus, your opponents will receive a message and won't be thinking you are away from keyboard. Clicking on this link is not mandatory, but we encourage its use for courtesy. d5068910b3fc89b88df76d2c81db4f101fd2d762 1370 1358 2015-02-10T13:20:02Z Anguishh 7978 /* Running out of time */ wikitext text/x-wiki [[Category:Help]] On '''Board Game Arena''' you are playing "live" (real time) or "turn-based" (asynchronously). In both cases, have an allotted delay to play your moves. Most of the time, your initial delay at the beginning of a game is some minutes (in realtime mode) or some days (in turn-based mode). During each turn, or on specific occasions, you get an additional delay. If you have no more time to play, you will get a "clock" penalty and your opponents can decide to skip your turns. == Time to think == Your allotted time to think is displayed on the right of your player's name. When it's your turn to play, this time is also displayed at the top of the web page. == Game speed == Table administrator can make a choice between some game speed profile (example: fast, normal, slow). There are many speeds for each mode (realtime and turn-based). The additional amount of time credited each turn depends on chosen game speed profile. Be careful to check game speed before game start to adapt your timing. The interface displays an estimation of the game duration based on recently played game with the same game and speed. Note: your allotted time to think cannot go higher that your initial time to think. For example, if you start the game with 5 minutes of thinking time, you time will be limited to 5 minutes maximum. Note: playing without time limit is strongly discouraged, except if you are playing with friends or to discover a new game. Remember that without time limit, you can't skip the turn of a player that is not playing. == Running out of time == As soon as you run out of time (negative clock), you get a clock penalty. '''For realtime games''': When a player has a negative clock, his opponents may make him skip his turn. Once this has been done, all following turns are skipped automatically. When you are in this situation (turns skipped automatically), you can get back in the game by clicking on the dedicated button "get back in this game". Note that you are not allowed to get back in the game if your clock is still negative. However, as all your turn are skipped, it shouldn't take long before your clock become positive again. If you can't/don't manage to get back in the game before the game end, you will get a "leave" penalty on your profile. '''For turn-based games''': On turn-based games, you are warned by email when you are running out of time. When you are out of time, your opponents receive an email to invite them to skip your turn. == Continue the game after a "skip turn" == If you are playing in a game where a player skip all his turn, you have 2 options: * You can continue to play the game until the end. This is recommended. In this case you will win ELO points you deserve for your victory. * You can abandon the game. All players with a negative clock will accept automatically. In this case, players who leaved the game get an ELO penalty (in addition to a "leave" penalty). == "My opponent is too slow" == Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his allotted time to think. If you want to play fast, set up or join table with "fast" mode only, but don't force an opponent to play when he has the right to do so. == "I would like to think a little" == If you are in a critical step of the game and want to take some time to think, you can click on the link "I would like to think a little" on the top right of the page. Thus, your opponents will receive a message and won't be thinking you are away from keyboard. Clicking on this link is not mandatory, but we encourage its use for courtesy. 95fdb72ed3a2a6fba4e42b160d0cf5b7bb5d0343 1373 1370 2015-02-17T22:03:59Z Een 3 wikitext text/x-wiki [[Category:Help]] On '''Board Game Arena''' you are playing "live" (real time) or "turn-based" (asynchronously). In both cases, you have an allotted delay to play your moves. Most of the time, your initial delay at the beginning of a game is some minutes (in realtime mode) or some days (in turn-based mode). During each turn, or on specific occasions, you get an additional delay. If you have no more time to play, you will get a "clock" penalty and your opponents can decide to skip your turns. == Time to think == Your allotted time to think is displayed on the right of your player's name. When it's your turn to play, this time is also displayed at the top of the web page. == Game speed == Table administrator can make a choice between some game speed profile (example: fast, normal, slow). There are many speeds for each mode (realtime and turn-based). The additional amount of time credited each turn depends on the chosen game speed profile. Be careful to check the game speed setting before the game starts to adjust your timing. The interface displays an estimation of the game duration based on recently played games with the same speed settings. Note: your allotted time to think cannot get higher that your initial time to think. For example, if you start the game with 5 minutes of thinking time, you time will be limited to 5 minutes maximum. Note: playing without a time limit is strongly discouraged, except if you are playing with friends, or to discover a new game. Remember that without time limit, you can't skip the turn of a player that is not playing. == Running out of time == As soon as you run out of time (negative clock), you get a clock penalty. '''For realtime games''': When a player has a negative clock, any one of his opponents can make him skip his turn. Once this has been done, all following turns are skipped automatically. When you are in this situation (turns skipped automatically), you can get back in the game by clicking on the dedicated button "get back in this game". Note that you are not allowed to get back in the game if your clock is still negative. However, as all your turn are skipped, it shouldn't take long before your clock becomes positive again. If you can't/don't manage to get back in the game before the game end, you will get a "leave" penalty on your profile. '''For turn-based games''': On turn-based games, you are warned by email when you are running out of time. When you are out of time, your opponents receive an email notifying them that they can make you skip your turn. == Continue the game after a "skip turn" == If you are playing in a game where a player skips all his turns, you have 2 options: * You can continue to play the game until the end. This is recommended. In this case you will earn the ELO points you deserve for your victory. * You can abandon the game. All players with a negative clock will accept automatically and receive both an ELO penalty and a "leave" penalty. But the you and the other players with a positive clock won't get any ELO since the game didn't reach its end). == "My opponent is too slow" == Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his allotted time to think. If you want to play fast, set up or join only tables with "fast" mode on, but don't bully an opponent to play when he has the right to use his alloted time to think. == "I would like to think a little" == If you are in a critical step of the game and want to take some time to think, you can click on the "I would like to think a little" link at the top right of the page. Thus, your opponents will get a message and won't be thinking that you are away from keyboard or disconnected. Clicking on this link is not mandatory, but we encourage its use as a courtesy. baeb7d9f7d981027f69ad1ac0d723a623f6668dc 1375 1373 2015-02-18T21:21:12Z Een 3 wikitext text/x-wiki [[Category:Help]] On '''Board Game Arena''' you are playing "live" (real time) or "turn-based" (asynchronously). In both cases, you have an allotted delay to play your moves. Most of the time, your initial delay at the beginning of a game is some minutes (in realtime mode) or some days (in turn-based mode). During each turn, or on specific occasions, you get an additional delay. If you have no more time to play, you will get a "clock" penalty and your opponents can decide to skip your turns. == Time to think == Your allotted time to think is displayed on the right of your player's name. When it's your turn to play, this time is also displayed at the top of the web page. == Game speed == Table administrator can make a choice between some game speed profile (example: fast, normal, slow). There are many speeds for each mode (realtime and turn-based). The additional amount of time credited each turn depends on the chosen game speed profile. Be careful to check the game speed setting before the game starts to adjust your timing. The interface displays an estimation of the game duration based on recently played games with the same speed settings. Note: your allotted time to think cannot get higher that your initial time to think. For example, if you start the game with 5 minutes of thinking time, you time will be limited to 5 minutes maximum. Note: playing without a time limit is strongly discouraged, except if you are playing with friends, or to discover a new game. Remember that without time limit, you can't skip the turn of a player that is not playing. == Running out of time == As soon as you run out of time (negative clock), you get a clock penalty. '''For realtime games''': When a player has a negative clock, any one of his opponents can make him skip his turn. Once this has been done, all following turns are skipped automatically. When you are in this situation (turns skipped automatically), you can get back in the game by clicking on the dedicated button "get back in this game". Note that you are not allowed to get back in the game if your clock is still negative. However, as all your turn are skipped, it shouldn't take long before your clock becomes positive again. If you can't/don't manage to get back in the game before the game end, you will get '''both''' a "leave" penalty on your profile and an ELO penalty for this game. '''For turn-based games''': On turn-based games, you are warned by email when you are running out of time. When you are out of time, your opponents also receive an email notifying them that they can make you skip your turn (they can also choose to wait if they don't mind or if you told them that you would be offline for some time). == Continue the game after a "skip turn" == If you are playing in a game where a player skips all his turns, you have 2 options: * You can continue to play the game until the end. This is recommended. In this case you will earn the ELO points you deserve for your victory. * You can abandon the game. All players with a negative clock will accept automatically and receive '''both''' an ELO penalty and a "leave" penalty. But the you and the other players with a positive clock won't get any ELO since the game didn't reach its end). == "My opponent is too slow" == Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his allotted time to think. If you want to play fast, set up or join only tables with "fast" mode on, but don't bully an opponent to play when he has the right to use his alloted time to think. == "I would like to think a little" == If you are in a critical step of the game and want to take some time to think, you can click on the "I would like to think a little" link at the top right of the page. Thus, your opponents will get a message and won't be thinking that you are away from keyboard or disconnected. Clicking on this link is not mandatory, but we encourage its use as a courtesy. fc4408e12098a9b59b7d64cc8a82507e832bbd73 Gamehelpthejellymonsterlab 0 141 1359 1020 2015-01-31T15:52:05Z Mrfe4rless 7876 supposed to be "a" instead on "an" wikitext text/x-wiki In The Jelly Monster Lab you are a scientist trying to make the best jelly monsters. In order to do it so, you need to move through the labs, trying to find the parts you need to make your monsters. At the beginning, every player starts with two experiments. Every experiment shows a monster made with a colored body (blue, red, pink or gren), eyes (1, 2 or 3) and a mouth (happy or sad) and a lab where you must make it. The parts are spread out over the six labs, so you move to them, and grab the parts you need to make your monsters, but you cannot have more than 5 cards in your hand. Once you have your experiment card and the parts, move to the lab indicated by the experiment card and leave all there (the experiment card and the parts). When other player come to visit that lab, it'll find your monster and then, it will be yours. While you're moving through the labs, you're leaving trails in order to know which player has been the last visiting it. If you move to a lab with a trail, there may be a monster of the owner of the trail. In addition, you can't move to a lab you were the last visit, so you need to program your moves to have all the parts of the experiment before you arrive to the lab where you must leave it with all the parts in your hand. In any time, you may want to go to the center to pick up a new experiment and make new monsters. But you'll not be able to go to the center if you just came from there (your meeple shows laid down) and if you have the maximum cards in hand (five). When a player has 4 monsters done, the center is open to close the game. Any player who goes there, finishes the game. Every monster has an score on it, depending on how difficult is to find their parts. You can see how many parts are in the game of each type, and what are all the experiments in the guide card placed on the bottom left corner of the playboard. The player with the most score points win the game. Advices: If you have experiments, one side too low scored, or on the other side too difficult to find the parts, you can leave the expèriment card in any lab, so other players can play with it, or maybe you can play with it in a later visit. 3aab63b2eace94cd2f08f115b9288cb9117828d2 Multipleaccounts 0 164 1360 1259 2015-02-04T09:36:44Z Cs cio 7908 /* Boosting your ELO by playing against yourself */ wikitext text/x-wiki == The Main Rule == '''One BGA account = One person''' == Playing from the same IP == This is '''authorized''' to play at the same table from the same IP (internet address). The warning message "this player plays from the same internet address as another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game. If you want to play from the same internet address as another person: * The best option is not to play at the same table, or play at a table where you know everyone. * If you play with strangers, make them comfortable with the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner. When some of your opponents are playing from the same IP: * You may politely refuse to play with them. * You should be vigilant and check that they are not collaborating during the game. * You don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report. == Boosting your ELO by playing against yourself == This is the most stupid and useless thing to do on BGA. Why? Because this is very easy to detect, and because the penalty is: * all your secondary account are removed. * your primary account is reset to 1500 ELO for all games. Why this is so easy to detect: * When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO. * In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game. * In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account". * Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless. If you have a lot of time to spend, please try to get better at this game and please do not try to cheat. 中文机器翻译: 主要规则 一个BGA帐户=一个人 从同一个IP玩 这是授权在同一IP同一桌玩(网络地址)。 警告消息“这个球员在相同的网络地址,另一名球员”是一个简单的警告。这是一个有用的警告,因为其他球员有权知道有球员在他们的桌子,可以讨论的游戏。 如果你想玩从相同的网络地址和另一个人: 最好的选择是不在同一张桌子上玩,或者玩的一张桌子上,每个人你都认识。 如果你玩的陌生人,让他们舒适的事实,你是2个(或更多)不同的人:不讨论在聊天室的游戏,不合作(或做kingmaking)与您的合作伙伴。 当你的对手是来自同一个IP玩: 你可以礼貌地拒绝和他们一起玩。 你要提高警惕,检查他们不合作的游戏中。 你不需要报告他们直到他们做一个混凝土kingmaking行动。如果你的报告有些球员说,“他们是在同一IP”没有任何kingmaking证明,我们将关闭你的报告。 在对自己提高你的ELO 这是最愚蠢和无用的东西做BGA。 为什么?因为这是很容易识别,因为刑罚: 你所有的次级帐户被删除。 您的主帐户被重置到1500以下所有游戏。 这是为什么那么容易察觉: 当你开始有一个很好的系统,好的其他队员都会看着你和你的游戏史。在游戏的历史,这是很容易看到你如何有一个好的ELO。 在BGA,每场比赛可以重播。所以如果一个游戏是怀疑,任何人都可以回放并检查,如果这是一个真正的游戏或一个假游戏。 此外,我们使用一些自动的方法和一些技术信息,让我们看看“一个人就是一个帐户”。 因此,它发生,有些球员做到ELO提升,但最后他们都发现和重置为1500。这就是为什么这是浪费大家的时间,这就是为什么这是无用的。 如果你有很多时间,请尝试在这方面做得更好的游戏,请不要试图欺骗。 5e882a262b09db10b45dd65c7b42477d118bc604 1361 1360 2015-02-04T09:47:17Z Cs cio 7908 /* Boosting your ELO by playing against yourself */ wikitext text/x-wiki == The Main Rule == '''One BGA account = One person''' == Playing from the same IP == This is '''authorized''' to play at the same table from the same IP (internet address). The warning message "this player plays from the same internet address as another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game. If you want to play from the same internet address as another person: * The best option is not to play at the same table, or play at a table where you know everyone. * If you play with strangers, make them comfortable with the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner. When some of your opponents are playing from the same IP: * You may politely refuse to play with them. * You should be vigilant and check that they are not collaborating during the game. * You don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report. == Boosting your ELO by playing against yourself == This is the most stupid and useless thing to do on BGA. Why? Because this is very easy to detect, and because the penalty is: * all your secondary account are removed. * your primary account is reset to 1500 ELO for all games. Why this is so easy to detect: * When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO. * In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game. * In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account". * Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless. If you have a lot of time to spend, please try to get better at this game and please do not try to cheat. '''忙郎中文机器翻译: 主要规则 一个BGA帐户=一个人。 警告消息“这个玩家与另一名玩家在相同的网络地址”是一个简单的警告。 这是一个有用的警告,因为其他玩家有权知道有玩家在他们的桌子,可以一起讨论游戏。 如果你想从相同的网络地址和另一个人玩,最好的选择是不在同一张桌子上玩,或者玩的一张桌子上,每个人你都认识。 如果跟你玩的是陌生人,让他们确认你们是2个不同的人:不讨论游戏,不与您的合作伙伴合作。 当你的对手是来自同一个IP:你可以礼貌地拒绝和他们一起玩。 你要提高警惕,检查他们游戏中不合作。 你不需要报告他们直到他们作弊。如果你报告说“他们是在同一IP”却没有任何证明,我们将关闭你的报告。 在对提高你自己的ELO方面,这是最愚蠢和无用的东西。为什么?因为这很容易识别,而且会有刑罚: 你所有的帐户被删除。您的主帐户所有游戏分值都将被重置到1500以下。 “一个人就是一个帐户”。 如果你有很多时间,请尝试在这方面做得更好的游戏,请不要试图欺骗。 ''' 0709537457f993109773f9998a1694f6b406483e First steps with BGA Studio 0 111 1362 934 2015-02-04T17:26:03Z Christopheryoder 621 /* Connect to your SFTP folder */ wikitext text/x-wiki == Connect to the BGA Studio website == Go to BGA Studio website: http://en.studio.boardgamearena.com Choose one of your 10 accounts (ex: myusername0), and login into the website - as you would do for Board Game Arena. == Check projects in progress and available game licences == On the left menu, you can check game projects under development and available game licences. From this point, you can choose what you want to do: * Join an existing project. * Create a new project. * Try to get a licence for a game you don't see in the "available game licences" page (see how-to on "available licences" page). == Create a new game project == You can do most of projects-related operation from "Control Panel / Manage games". In particular, you can create a new project automatically from there. == Connect to your SFTP folder == From the initial email from the Studio you get: * the name of the SFTP server to connect to * your SFTP login and password Using this information: # Connect to the SFTP server using your SFTP login and password, through your favourite SFTP client software (such as [http://winscp.net/ WinSCP] for example) # Check that your home folder contains one folder for each of the three example games (reversi, hearts, gomoku). If you have already created a new game project, one additional folder should be in your "home" folder. == Let's code! == Now, you can try to launch a new game on BGA Studio from the "Play now" menu entry, as you would do on Board Game Arena website. # Find your game in the 'Play now' section and launch a table # Use the 'I want between X and X' players to tick down the maximum players number to the minimum # Click 'Express start': your game launches with the maximum number of players specified. It shows an empty canvas: in the game zone you just have a sentence 'This is your game interface. You can edit this HTML in your ".tpl" file.'. # Switch to your SFTP home folder, go into your game folder. Edit the game_game.tpl file, and change this sentence to 'Hey, this is my first game!', then save. # Go back to your browser and refresh, check that the game zone has updated. # Click on the 'Exit game' icon on the top right, and in the popup choose 'Express game stop'. The game ends automatically and you are brought back to the table screen for this ended game. # Switch to your game folder, go into the img folder and overwrite your game_box.png file with another image. # Go back to your browser, '''empty your browser cache''', then refresh the page, and check that the game box image has been updated. Then you can modify the provided skeleton and begin to develop your game :) == Commit your changes == Committing uploads your changes on our [http://en.wikipedia.org/wiki/Revision_control revision control] system. This is an extra assurance not to lose your code, and to have the possibility to get a previous version of your code if you need to backtrack. It also helps us to follow your progress (we get an email when you commit). So you should commit from time to time, when you hit some landmark in your development. You can automatically commit your sources in the repository from "Control Panel / Manage Games / Your games / Commit my modifications". Then: # Enter your commit comment (such as 'My first commit') then hit the 'Submit' button; # Check the log for errors, it should end with the following lines: Transmitting file data . Committed revision #revision number#. HAL says: done. == That's all! == Now you know about the basics of updating your game on BGA Studio and testing your changes. For more information on the specificites of each file, please check out the [[Studio#BGA_Studio_documentation | reference documentation for the framework]]. 15ce2e60998576500e0b6501d4d8d008624efcdc Tutorial reversi 0 57 1363 1047 2015-02-05T16:46:17Z Christopheryoder 621 /* The rules */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for white and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('img/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "states.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where she is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where she is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight squares where player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in state.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 7aa05f99cf9cebbc661d5cd5ca636b0237afa8bc 1364 1363 2015-02-05T16:47:43Z Christopheryoder 621 /* Display allowed moves */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for white and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('img/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "states.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where she is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where she is allowed to play. This method will be used in particular: * As we just said, to help the player to see where he can play. * When the player play, to check if he has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight the squares where the player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in state.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 8ab818739573367c8816e3449a71e926614dbf41 1365 1364 2015-02-05T16:49:17Z Christopheryoder 621 /* The rules */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for white and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('img/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "states.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where she is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where she is allowed to play. This method will be used in particular: * As we just said, to help the player to see where she can play. * When the player play, to check if she has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight the squares where the player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in state.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". f88d4ab06248027fd26cb3cd4b4a56ac7653801a 1366 1365 2015-02-05T16:51:05Z Christopheryoder 621 /* The rules */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for white and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('img/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "states.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where she is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where she is allowed to play. This method will be used in particular: * As we just said, to help the player to see where she can play. * When the player plays, to check if she has the right to play here. This is pure PHP programming here, and there's no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight the squares where the player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in state.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 341a04d49a317161a688f525ae6b2387c2799e6b 1367 1366 2015-02-05T16:51:56Z Christopheryoder 621 /* The rules */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for white and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('img/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "states.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where she is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where she is allowed to play. This method will be used in particular: * As we just said, to help the player to see where she can play. * When the player plays, to check if she has the right to play here. This is pure PHP programming here, and there are no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight the squares where the player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in state.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 690b74d41e590480e30dc1107031e5794bc75c8f 1369 1367 2015-02-05T19:36:23Z Christopheryoder 621 /* Let's play */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for white and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('img/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "states.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where she is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where she is allowed to play. This method will be used in particular: * As we just said, to help the player to see where she can play. * When the player plays, to check if she has the right to play here. This is pure PHP programming here, and there are no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight the squares where the player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on the server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in state.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". ce1c16276b7d1d71c79144430c0be3c75f7be34b Players actions: yourgamename.action.php 0 85 1368 495 2015-02-05T19:31:52Z Christopheryoder 621 /* Useful tip: retrieve a list of number */ wikitext text/x-wiki == Purpose of this file == With this file, you define all the players entry points (ie: possible game actions) of your game. This file is a sort of "bridge" between the AJAX calls you are doing from your Javascript client side, and your main PHP code in "yourgame.game.php". The role of the methods defined in this file is to filter the arguments, eventually to format them a little bit, and then to call a corresponding PHP method from your main game logic ("yourgame.game.php" file). Methods in this file must be short: no game logic must be introduced here. == Example of typical action method == (from Reversi example) <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> == Methods to use in action methods == '''function setAjaxMode''' Must be use at the beginning of each action method. '''function ajaxResponse''' Must be use at the end of each action method. '''function getArg( $argName, $argType, $mandatory=false, $default=NULL, $argTypeDetails=array(), $bCanFail=false )''' This method must be used to retrieve the arguments sent with your AJAX query. You must NOT use "_GET", "_POST" or equivalent PHP variables to do this, as it is unsafe. This method use the following arguments: * argName: the name of the argument to retrieve. * argType: the type of the argument. You should use one of the following: 'AT_int' for an integer 'AT_posint' for a positive integer 'AT_float' for a float 'AT_bool' for 1/0/true/false 'AT_enum' for an enumeration (argTypeDetails list the possible values as an array) 'AT_alphanum' for a string with 0-9a-zA-Z_ and space 'AT_numberlist' for a list of several numbers separated with "," or ";" (ex: exemple: 1,4;2,3;-1,2). * mandatory: specify "true" if the argument is mandatory. * default: if mandatory=false, you can specify here a default value in case the argument is not present. * argTypeDetails: see AT_enum above. * bCanFail: if true, specify that it may be possible that the argument won't be of the type specified by argType (and then do not log this as a fatal error in the system, and return a standard exception to the player). '''function isArg( $argName )''' This is a useful method when you only want to check if an argument is present or not present in your AJAX request (and don't care of the value. It returns "true" or "false" whether "argName" has been specified as an argument of the AJAX request or not. == Useful tip: retrieve a list of numbers == If your Javascript sends a list of integers separated by ";" (ex: "1;2;3;4") as an argument, you can transform them in a PHP array with the following: <pre> public function playCards() { self::setAjaxMode(); $card_ids_raw = self::getArg( "card_ids", AT_numberlist, true ); // Removing last ';' if exists if( substr( $card_ids_raw, -1 ) == ';' ) $card_ids_raw = substr( $card_ids_raw, 0, -1 ); if( $card_ids_raw == '' ) $card_ids = array(); else $card_ids = explode( ';', $card_ids_raw ); $this->game->playCards( $card_ids ); self::ajaxResponse( ); } </pre> 982b4df9c218fe043a7f4a53fd52666b22e19f59 Gamehelpsechsnimmt 0 174 1371 1284 2015-02-12T06:26:32Z Inkybloc 7996 /* Playing the game */ added "from lowest value played to highest" for clarification wikitext text/x-wiki == 6 nimmt! == The basic goal of the game is to avoid having to pick up cards, and try to force the other players to do so. Everyone starts with 66 points - you lose one for each "beef head" on a card you have to pick up. When one player has lost all of their points, the game will end at the end of the current round and the player with the most points left wins! === Playing the game === Everyone starts a round with 10 cards in their hand. Four cards are placed on the table to start four rows. Every player secretly chooses a card, and then all of the cards are revealed at the same time. When the cards are revealed, they are placed on the ends of rows, from lowest value played to highest, following two rules: 1. cards are always placed in ascending order. 2. cards are always placed next to the card on the board with the smallest difference between them. As play progresses, the rows will fill up with cards - at five cards, a row is full. If someone's card would go onto a full row, that player has to pick up all of the cards in that row, and they lose as many points as there are "beef heads" on the cards (different cards are worth different amounts - more on that in a moment). The card that the person played becomes the starting point of a new row. If someone plays a card that is lower than then numbers at the end of all of the rows, then that player must take a row of their choice, and start a new row in its place with their card. '''Bull heads''' Each card has a number of bull heads on it - this indicates how many points it is worth when it is picked up. Cards which end in the number "5" (ex. 5, 15, 25) are worth 2 points. Cards which end in the number "0" (10, 20, 30) are worth 3 points. Cards which have double numbers (11, 22, 33) are worth 5 points. The "55" card has both a "5" and double numbers, and is worth 7 points. All other cards are worth 1 point. '''End of a round''' Once a round ends, if no one has lost all of their points, then a new round begins. If someone is out of points, then the game is over and whoever still has the most points is the winner. === Alternate Rules === '''Tactics:''' This ruleset changes the number of cards in play based on how many people are playing - other than that the rules are the same. The number of cards is equal to the number of players plus 4, so every card that could be played will find its way onto the table at some point. This changes strategy some and makes paying attention to which cards are have yet to be played important. '''Logic:''' The same as Tactics, except that at the start of the round all of the cards are placed on the table face up, and players take turns choosing cards one at a time to build their hands before the round proper starts. f90ae1639bb14e4736c6bafa61272d13abba1760 Gamehelpsaboteur 0 32 1374 1196 2015-02-18T19:13:34Z Barrabus 8053 wikitext text/x-wiki == Goal == Get as many gold nuggets as possible during the three rounds of the game. In order to do so, # if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards # if you are a '''saboteur''', you must, in association with other gold diggers, prevent the gold diggers to get to the treasure. Your role (gold digger or saboteur) will be randomly selected at the start of each round. == Rules summary == On your turn, you must click on a card from your hand to select it, then play this card or discard it. You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card. The cards are of several types: * 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card. * 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score). A player with a broken tool cannot play a Path card. * 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you. * 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about. * 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove. == Cards in play == * 44 'Path' cards * 9 'Sabotage' cards (three for each tool) * 6 'Repair a tool' cards (two for each tool) * 3 'Repair a tool among these two' cards (one for each combination of two tools) * 5 'Map' cards (one less than in the box set, as requested by the game author) * 3 'Rock fall' cards * 28 'Gold' cards ** 16 with one gold nugget ** 8 with two gold nuggets ** 4 with three gold nuggets == Roles == Roles are randomly selected among a set that depends upon the number of players: * with 3 players: 1 saboteur and 3 gold diggers * with 4 players: 1 saboteur and 4 gold diggers * with 5 players: 2 saboteurs and 4 gold diggers * with 6 players: 2 saboteurs and 5 gold diggers * with 7 players: 3 saboteurs and 5 gold diggers * with 8 players: 3 saboteurs and 6 gold diggers * with 9 players: 3 saboteurs and 7 gold diggers * with 10 players: 4 saboteurs and 7 gold diggers == Available variants == The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum! '''Have a good game !''' e5e1bb9689a5ae854c3c0bcd11787caf98ff6f30 Rating 0 16 1376 1130 2015-02-21T02:31:19Z Carlr 8079 Added info for Beginner and Average player Elo ratings. Improved some difficult to read sentences, and corrected some english grammar. Changed 'ELO' to 'Elo', as it is not an acronym. It is a person's name. wikitext text/x-wiki [[Category:Help]] == What is an Elo rating? == Your Elo rating for a game is an indicator of your level of skill at that game. It's a 4 digit number followed by the symbol http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you've never played a game on BGA, your initial rating will be 1500. Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game? == The number of Elo points gained or lost in a game depends on (1) the Elo rating of your opponents, and (2) what place you achieve in the game (i.e. 1st place, 2nd place). For example: * If you end the game in a better position than a player with a higher Elo, you gain a lot of points. * If you end the game in a better position than a player with a lower Elo, you gain fewer points. * If you end the game in a worse position than a player with a lower Elo, you lose a lot points. * And so on... == Some advice == * There's little to be gained by beating players with an Elo rating a lot lower than yours. Try to find opponents with a similar Elo rating to yourself: it's both more fun and better for your Elo. * What place you achieve in a game is very important when calculating the Elo. This is why it is important to continue fighting for minor places in the game even if you think you can't win. * The number of Elo points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you lose as many points as if you had finished the game in last place, plus an additional penalty of 10 points. Even if you are in a difficult situation it is in your interest to play the game until the end - or concede the victory to your opponent. == How is my Elo rating computed? == The BGA Elo system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system Elo rating system] in use for chess. The Elo system's main principle is the following: the Elo points difference between 2 players determines the probability of each of them winning an encounter. If two players have the same Elo, they have an equal (50/50) probability of winning. If one player has 400 more points than the other, his probability of winning is 90%. Elo points gains and losses will, over time, tend to adjust the Elo rating of each player to reflect the actual probability that either of them will win a particular encounter. Some changes have been made to the Elo system used on BGA: * During your first 30 games, your Elo rating is more "elastic": you can win (or lose) more points in each game. This way, your Elo rating converges faster to you "natural" rating. * The original Elo rating system was designed for 2 player games. For games with more than 2 players, BGA considers (for the Elo rating) that you win a 2-player game against each opponent who placed below you, and that you lose a 2-player game against each who place above you. * Games with more than 2 players last longer. For this reason, there are more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula! == The formula is exactly the one used by the Elo rating system, with the following adjustments: * First of all, if someone leaves a game for any reason this game is not taken into account by the Elo rating system. * K=60 for the first 30 games, K=40 afterwards. * K is multiplied by (N/2) for N-player games. If N exceeds the "advised number of players" for this game, K is multiplied by (A/2), where A is the "advised number of players". * If 2 players have a rating difference greater than 600, we consider that their ELO difference is 600. == Beginners, Average players, Good players, Experts, Masters == * Beginner: Everyone starts as a Beginner. * Average level players are players <1600 Elo with at least one victory. * Good: > 1600 Elo * Expert: > 1800 Elo * Master: > 2000 Elo 40392b6745f572eb8bf6ccd93ca294a2ca642bb1 1377 1376 2015-02-21T02:32:50Z Carlr 8079 /* Okay, but I want to know the formula! */ wikitext text/x-wiki [[Category:Help]] == What is an Elo rating? == Your Elo rating for a game is an indicator of your level of skill at that game. It's a 4 digit number followed by the symbol http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you've never played a game on BGA, your initial rating will be 1500. Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game? == The number of Elo points gained or lost in a game depends on (1) the Elo rating of your opponents, and (2) what place you achieve in the game (i.e. 1st place, 2nd place). For example: * If you end the game in a better position than a player with a higher Elo, you gain a lot of points. * If you end the game in a better position than a player with a lower Elo, you gain fewer points. * If you end the game in a worse position than a player with a lower Elo, you lose a lot points. * And so on... == Some advice == * There's little to be gained by beating players with an Elo rating a lot lower than yours. Try to find opponents with a similar Elo rating to yourself: it's both more fun and better for your Elo. * What place you achieve in a game is very important when calculating the Elo. This is why it is important to continue fighting for minor places in the game even if you think you can't win. * The number of Elo points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you lose as many points as if you had finished the game in last place, plus an additional penalty of 10 points. Even if you are in a difficult situation it is in your interest to play the game until the end - or concede the victory to your opponent. == How is my Elo rating computed? == The BGA Elo system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system Elo rating system] in use for chess. The Elo system's main principle is the following: the Elo points difference between 2 players determines the probability of each of them winning an encounter. If two players have the same Elo, they have an equal (50/50) probability of winning. If one player has 400 more points than the other, his probability of winning is 90%. Elo points gains and losses will, over time, tend to adjust the Elo rating of each player to reflect the actual probability that either of them will win a particular encounter. Some changes have been made to the Elo system used on BGA: * During your first 30 games, your Elo rating is more "elastic": you can win (or lose) more points in each game. This way, your Elo rating converges faster to you "natural" rating. * The original Elo rating system was designed for 2 player games. For games with more than 2 players, BGA considers (for the Elo rating) that you win a 2-player game against each opponent who placed below you, and that you lose a 2-player game against each who place above you. * Games with more than 2 players last longer. For this reason, there are more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula! == The formula is exactly the one used by the Elo rating system, with the following adjustments: * First of all, if someone leaves a game for any reason this game is not taken into account by the Elo rating system. * K=60 for the first 30 games, K=40 afterwards. * K is multiplied by (N/2) for N-player games. If N exceeds the "advised number of players" for this game, K is multiplied by (A/2), where A is the "advised number of players". * If 2 players have a rating difference greater than 600, we consider that their Elo difference is 600. == Beginners, Average players, Good players, Experts, Masters == * Beginner: Everyone starts as a Beginner. * Average level players are players <1600 Elo with at least one victory. * Good: > 1600 Elo * Expert: > 1800 Elo * Master: > 2000 Elo 52a036e4068f49d0f49c531392d47d380f78865a 1378 1377 2015-02-21T02:46:31Z Carlr 8079 /* Beginners, Average players, Good players, Experts, Masters */ wikitext text/x-wiki [[Category:Help]] == What is an Elo rating? == Your Elo rating for a game is an indicator of your level of skill at that game. It's a 4 digit number followed by the symbol http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you've never played a game on BGA, your initial rating will be 1500. Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game? == The number of Elo points gained or lost in a game depends on (1) the Elo rating of your opponents, and (2) what place you achieve in the game (i.e. 1st place, 2nd place). For example: * If you end the game in a better position than a player with a higher Elo, you gain a lot of points. * If you end the game in a better position than a player with a lower Elo, you gain fewer points. * If you end the game in a worse position than a player with a lower Elo, you lose a lot points. * And so on... == Some advice == * There's little to be gained by beating players with an Elo rating a lot lower than yours. Try to find opponents with a similar Elo rating to yourself: it's both more fun and better for your Elo. * What place you achieve in a game is very important when calculating the Elo. This is why it is important to continue fighting for minor places in the game even if you think you can't win. * The number of Elo points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you lose as many points as if you had finished the game in last place, plus an additional penalty of 10 points. Even if you are in a difficult situation it is in your interest to play the game until the end - or concede the victory to your opponent. == How is my Elo rating computed? == The BGA Elo system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system Elo rating system] in use for chess. The Elo system's main principle is the following: the Elo points difference between 2 players determines the probability of each of them winning an encounter. If two players have the same Elo, they have an equal (50/50) probability of winning. If one player has 400 more points than the other, his probability of winning is 90%. Elo points gains and losses will, over time, tend to adjust the Elo rating of each player to reflect the actual probability that either of them will win a particular encounter. Some changes have been made to the Elo system used on BGA: * During your first 30 games, your Elo rating is more "elastic": you can win (or lose) more points in each game. This way, your Elo rating converges faster to you "natural" rating. * The original Elo rating system was designed for 2 player games. For games with more than 2 players, BGA considers (for the Elo rating) that you win a 2-player game against each opponent who placed below you, and that you lose a 2-player game against each who place above you. * Games with more than 2 players last longer. For this reason, there are more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula! == The formula is exactly the one used by the Elo rating system, with the following adjustments: * First of all, if someone leaves a game for any reason this game is not taken into account by the Elo rating system. * K=60 for the first 30 games, K=40 afterwards. * K is multiplied by (N/2) for N-player games. If N exceeds the "advised number of players" for this game, K is multiplied by (A/2), where A is the "advised number of players". * If 2 players have a rating difference greater than 600, we consider that their Elo difference is 600. == Beginners, Average players, Good players, Experts, Masters == * Beginner: Everyone starts as a Beginner. You stay a Beginner until you acheive a victory, regardless of your Elo. If you have at least 1 victory, the following levels apply, bepending on your Elo: * Average: < 1600 * Good: >= 1600 * Expert: >= 1800 * Master: >= 2000 119bd2f982a614b9735dcae5b428b1892a23e927 1379 1378 2015-02-21T02:47:53Z Carlr 8079 spelling wikitext text/x-wiki [[Category:Help]] == What is an Elo rating? == Your Elo rating for a game is an indicator of your level of skill at that game. It's a 4 digit number followed by the symbol http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you've never played a game on BGA, your initial rating will be 1500. Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game? == The number of Elo points gained or lost in a game depends on (1) the Elo rating of your opponents, and (2) what place you achieve in the game (i.e. 1st place, 2nd place). For example: * If you end the game in a better position than a player with a higher Elo, you gain a lot of points. * If you end the game in a better position than a player with a lower Elo, you gain fewer points. * If you end the game in a worse position than a player with a lower Elo, you lose a lot points. * And so on... == Some advice == * There's little to be gained by beating players with an Elo rating a lot lower than yours. Try to find opponents with a similar Elo rating to yourself: it's both more fun and better for your Elo. * What place you achieve in a game is very important when calculating the Elo. This is why it is important to continue fighting for minor places in the game even if you think you can't win. * The number of Elo points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you lose as many points as if you had finished the game in last place, plus an additional penalty of 10 points. Even if you are in a difficult situation it is in your interest to play the game until the end - or concede the victory to your opponent. == How is my Elo rating computed? == The BGA Elo system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system Elo rating system] in use for chess. The Elo system's main principle is the following: the Elo points difference between 2 players determines the probability of each of them winning an encounter. If two players have the same Elo, they have an equal (50/50) probability of winning. If one player has 400 more points than the other, his probability of winning is 90%. Elo points gains and losses will, over time, tend to adjust the Elo rating of each player to reflect the actual probability that either of them will win a particular encounter. Some changes have been made to the Elo system used on BGA: * During your first 30 games, your Elo rating is more "elastic": you can win (or lose) more points in each game. This way, your Elo rating converges faster to you "natural" rating. * The original Elo rating system was designed for 2 player games. For games with more than 2 players, BGA considers (for the Elo rating) that you win a 2-player game against each opponent who placed below you, and that you lose a 2-player game against each who place above you. * Games with more than 2 players last longer. For this reason, there are more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula! == The formula is exactly the one used by the Elo rating system, with the following adjustments: * First of all, if someone leaves a game for any reason this game is not taken into account by the Elo rating system. * K=60 for the first 30 games, K=40 afterwards. * K is multiplied by (N/2) for N-player games. If N exceeds the "advised number of players" for this game, K is multiplied by (A/2), where A is the "advised number of players". * If 2 players have a rating difference greater than 600, we consider that their Elo difference is 600. == Beginners, Average players, Good players, Experts, Masters == * Beginner: Everyone starts as a Beginner. You stay a Beginner until you achieve a victory, regardless of your Elo. If you have at least 1 victory, the following levels apply, depending on your Elo: * Average: < 1600 * Good: >= 1600 * Expert: >= 1800 * Master: >= 2000 e4eabcf7e93be554c6d72f490e90f6c11b789dde Gamehelpyatzy 0 122 1380 1189 2015-02-23T18:49:11Z Andreicho 8117 wikitext text/x-wiki The game Yahtzee consists of 13 rounds. In each round, you roll 5 dice and then score the roll in a different category of your choice. During a round, you can roll the dice up to three times before scoring -- the initial roll (in which you must roll all the dice), plus two optional re-rolls of any or all dice. There are 13 scoring categories, and each must be used for one of the 13 rounds. This often results in a zero score for some categories. The 13 scoring categories are as follows: 1-6: There is one category for each number on the die. In these categories, the score is the sum of the pips on the dice of that number. For example, a roll of 1-1-2-5-5 could be scored as 2 points in the "ones" category, 2 points in the "twos" category, 10 points in the "fives" category, or 0 points in the "threes," "fours," or "sixes." If a player scores a total of at least 63 points across these six boxes, a bonus of 35 points is added. 7. Three-Of-A-Kind: At least three dice showing the same face -- Points equal the sum of all 5 dice (not just the 3 of a kind) 8. Four-Of-A-Kind: At least four dice showing the same face -- Points equal the sum of all 5 dice (not just the 4 of a kind) 9. Full House: A three-of-a-kind and a pair -- 25 points 10. Small Straight: Four sequential dice 1-2-3-4, 2-3-4-5, or 3-4-5-6) -- 30 points 11. Large Straight: Five sequential dice (1-2-3-4-5 or 2-3-4-5-6) -- 40 points 12. Yahtzee: All five dice showing the same face -- 50 points (plus, once you have scored 50 pts for a Yahtzee, a 2nd Yahtzee gives a bonus of 100 points) 13. Chance: Any combination -- points equal the sum of all 5 dice 14. Rigole: 4 times the same number and 1 time the opposite number on a dice (Ex. 1-1-1-1-6, 2-2-2-2-5, 3-3-3-3-4, 4-4-4-4-3, 5-5-5-5-2, 6-6-6-6-1) 47a189a52c36df03f63aa9ac6e8ec1fdf64646f4 Gamehelppolis 0 179 1381 1326 2015-02-24T03:49:19Z Wentley 8121 /* Military Actions (cost 1 Prestige) */ wikitext text/x-wiki == Development Actions == # Create Hoplites: Only in one polis per turn; pay 1 metal (or silver) per hoplite # Create Galleys: Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). # Create Merchants: Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == # Move Hoplites: Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories, but not both); sea movement must be from and to a port: territories controlled by opponent block movement. # Move Galleys: Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. # Besiege Polis: Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: * If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). * If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. # Collection: Take resources corresponding to number of hoplites from the region placed in Tribute Box. Place disk to show region exhausted and return hoplites. No Prestige cost for action in home region. == Political Actions == # Trade: Move one merchant via free trade route to Foreign Market and place it on available shipload: * Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). * Purchase (silver paid for wheat); then increase market value (roll die twice; use higher result to move marker left). # Move Proxenos: Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). # Redeem Proxenos: Pay 2 silver to opponent; place Proxenos in capital. # Instigate Civil War: Proxenos needed; action costs 2x Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: * not matching: defender loses 1 unit, attacker gains Prestige on card. * matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: # not enough cards are left in the Combat Card deck. # one player retreats (and pays 1 Prestige to opponent). # one player has less than 2 units left. == End of the Round == # Projects: all are completed, and award immediate Prestige. # Supply: player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. # Growth: increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. # Megalopolis: 1 Prestige awarded for every polis exceeding Base Population. # Storage: halve amount of oil, wine, and wheat in storage (rounded up) # Phoros: exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == # A player cannot supply enough wheat/Prestige to feed his capital. # A player does not have any Prestige left after “End of Round” phase. # The fourth round (5β) has been finished. == Final Score == * total of Population Cubes in all poleis, plus * current Prestige, plus * ”Prestige for Posterity” (on project tiles). b51c1a92ccf9040d3eb844239722545fd0199b9c 1382 1381 2015-02-24T04:03:39Z Wentley 8121 /* Military Actions (cost 1 Prestige) */ wikitext text/x-wiki == Development Actions == # Create Hoplites: Only in one polis per turn; pay 1 metal (or silver) per hoplite # Create Galleys: Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). # Create Merchants: Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == # Move Hoplites: Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories, but not both); sea movement must be from and to a port: territories controlled by opponent (with greater number of units) block movement. # Move Galleys: Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. # Besiege Polis: Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: * If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). * If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. # Collection: Take resources corresponding to number of hoplites from the region placed in Tribute Box. Place disk to show region exhausted and return hoplites. No Prestige cost for action in home region. == Political Actions == # Trade: Move one merchant via free trade route to Foreign Market and place it on available shipload: * Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). * Purchase (silver paid for wheat); then increase market value (roll die twice; use higher result to move marker left). # Move Proxenos: Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). # Redeem Proxenos: Pay 2 silver to opponent; place Proxenos in capital. # Instigate Civil War: Proxenos needed; action costs 2x Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: * not matching: defender loses 1 unit, attacker gains Prestige on card. * matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: # not enough cards are left in the Combat Card deck. # one player retreats (and pays 1 Prestige to opponent). # one player has less than 2 units left. == End of the Round == # Projects: all are completed, and award immediate Prestige. # Supply: player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. # Growth: increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. # Megalopolis: 1 Prestige awarded for every polis exceeding Base Population. # Storage: halve amount of oil, wine, and wheat in storage (rounded up) # Phoros: exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == # A player cannot supply enough wheat/Prestige to feed his capital. # A player does not have any Prestige left after “End of Round” phase. # The fourth round (5β) has been finished. == Final Score == * total of Population Cubes in all poleis, plus * current Prestige, plus * ”Prestige for Posterity” (on project tiles). 2072964877e88605c68ccf5b9f8bd2a76774746b 1383 1382 2015-02-25T18:57:40Z Wentley 8121 /* Political Actions */ wikitext text/x-wiki == Development Actions == # Create Hoplites: Only in one polis per turn; pay 1 metal (or silver) per hoplite # Create Galleys: Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). # Create Merchants: Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == # Move Hoplites: Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories, but not both); sea movement must be from and to a port: territories controlled by opponent (with greater number of units) block movement. # Move Galleys: Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. # Besiege Polis: Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: * If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). * If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. # Collection: Take resources corresponding to number of hoplites from the region placed in Tribute Box. Place disk to show region exhausted and return hoplites. No Prestige cost for action in home region. == Political Actions == # Trade: Move one merchant via free trade route to Foreign Market and place it on available shipload: * Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). * Purchase (silver paid for wheat); then decrease market value (roll die twice; use higher result to move marker left). # Move Proxenos: Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). # Redeem Proxenos: Pay 2 silver to opponent; place Proxenos in capital. # Instigate Civil War: Proxenos needed; action costs 2x Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: * not matching: defender loses 1 unit, attacker gains Prestige on card. * matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: # not enough cards are left in the Combat Card deck. # one player retreats (and pays 1 Prestige to opponent). # one player has less than 2 units left. == End of the Round == # Projects: all are completed, and award immediate Prestige. # Supply: player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. # Growth: increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. # Megalopolis: 1 Prestige awarded for every polis exceeding Base Population. # Storage: halve amount of oil, wine, and wheat in storage (rounded up) # Phoros: exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == # A player cannot supply enough wheat/Prestige to feed his capital. # A player does not have any Prestige left after “End of Round” phase. # The fourth round (5β) has been finished. == Final Score == * total of Population Cubes in all poleis, plus * current Prestige, plus * ”Prestige for Posterity” (on project tiles). b9852ab0ff3644a2efed601279d449656b60cb30 1384 1383 2015-02-25T20:19:53Z Wentley 8121 /* Military Actions (cost 1 Prestige) */ wikitext text/x-wiki == Development Actions == # Create Hoplites: Only in one polis per turn; pay 1 metal (or silver) per hoplite # Create Galleys: Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). # Create Merchants: Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == # Move Hoplites: Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories, but not both); territories controlled by opponent (with greater number of units) block movement. # Move Galleys: Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. # Besiege Polis: Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: * If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). * If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. # Collection: Take resources corresponding to number of hoplites from the region placed in Tribute Box. Place disk to show region exhausted and return hoplites. No Prestige cost for action in home region. == Political Actions == # Trade: Move one merchant via free trade route to Foreign Market and place it on available shipload: * Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). * Purchase (silver paid for wheat); then decrease market value (roll die twice; use higher result to move marker left). # Move Proxenos: Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). # Redeem Proxenos: Pay 2 silver to opponent; place Proxenos in capital. # Instigate Civil War: Proxenos needed; action costs 2x Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: * not matching: defender loses 1 unit, attacker gains Prestige on card. * matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: # not enough cards are left in the Combat Card deck. # one player retreats (and pays 1 Prestige to opponent). # one player has less than 2 units left. == End of the Round == # Projects: all are completed, and award immediate Prestige. # Supply: player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. # Growth: increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. # Megalopolis: 1 Prestige awarded for every polis exceeding Base Population. # Storage: halve amount of oil, wine, and wheat in storage (rounded up) # Phoros: exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == # A player cannot supply enough wheat/Prestige to feed his capital. # A player does not have any Prestige left after “End of Round” phase. # The fourth round (5β) has been finished. == Final Score == * total of Population Cubes in all poleis, plus * current Prestige, plus * ”Prestige for Posterity” (on project tiles). dbef0d66b7d091e3bd7421f37ba594a259926f5f Gamehelptzolkin 0 129 1385 1306 2015-02-25T21:08:21Z Kevkev60614 8131 wikitext text/x-wiki Rules are here: http://czechgames.com/files/rules/tzolkin-2-rules-en.pdf == '''For Each Round''' == - Each player takes their turn, going around the table - On a food day, feed your workers and take your rewards - Advance the Calendar == '''Player turn''' == - '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple) - '''Either place workers OR pick up workers''' -- ''Placing workers'': pay corn for the number of workers you place. The cost for the number of workers you place is 0, 1, 3, 6, 10, or 15 for, respectively, 1, 2, 3, 4, 5, or 6 workers placed on that turn, plus the cumulative cost noted next to each of your placed workers. -- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either --- Use the action where your worker was standing --- Use a lower action on the wheel from where your worker was standing(if not standing on a free action space,pay 1 corn for each step back) --- Do nothing. == '''Food Day''' == -'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for. -- For each worker not fed, you lose 3 points -'''Take Rewards''' --''Middle of Age (Brown days)'' --- Receive items shown on the left edge of temples from step you are on and all steps below -- ''End of Age (Teal Days)'' --- Remove all Age 1 buildings and fill spaces with Age 2 buildings --- Receive points shown on the right edge of temples for the step you are on. --- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus. == '''Advance the Calendar''' == If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day. Otherwise: - The worker on the Starting Player space returns to the player -- If this person was not the starting player, they take the starting player marker. -- If they were the starting player, the starting player marker is moved to the player on his left - Advance the Tzolk'in Gear one day. - The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears. -- If you use this option, flip your board to dark side up. -- This does not avoid food days. f27763ba6f53f6fdb9b5a51374ddc1b8e2fb7993 1386 1385 2015-02-25T21:21:08Z Kevkev60614 8131 wikitext text/x-wiki Rules are here: http://czechgames.com/files/rules/tzolkin-rules-en.pdf == '''For Each Round''' == - Each player takes their turn, going around the table - On a food day, feed your workers and take your rewards - Advance the Calendar == '''Player turn''' == - '''Beg for corn:''' If you have 2 or less corn, you may beg for corn unless you are at the bottom step of all three temples. (Turn in all corn, take 3 corn and move one step down on any temple) - '''Either place workers OR pick up workers''' -- ''Placing workers'': pay corn for the number of workers you place. The cost for the number of workers you place is 0, 1, 3, 6, 10, or 15 for, respectively, 1, 2, 3, 4, 5, or 6 workers placed on that turn, plus the cumulative cost noted next to each of your placed workers. -- ''Picking up Workers'': You may pick up one or more of your placed workers. For each worker picked up either --- Use the action where your worker was standing --- Use a lower action on the wheel from where your worker was standing(if not standing on a free action space,pay 1 corn for each step back) --- Do nothing. == '''Food Day''' == -'''Feed the Workers''' Each players must pay 2 corn for each worker they have in play (on a gear or in front of you) with the exception for any farms you own. You must feed as many workers as you have corn for. -- For each worker not fed, you lose 3 points -'''Take Rewards''' --''Middle of Age (Brown days)'' --- Receive items shown on the left edge of temples from step you are on and all steps below -- ''End of Age (Teal Days)'' --- Remove all Age 1 buildings and fill spaces with Age 2 buildings --- Receive points shown on the right edge of temples for the step you are on. --- Bonus points for each temple for person with the highest market. Bonus amount is shown above each temple. For ties, everyone receives half the bonus. == '''Advance the Calendar''' == If there is no worker on the starting player space, place a corn on the current Tzolk'in gear tooth and advance the gear one day. Otherwise: - The worker on the Starting Player space returns to the player -- If this person was not the starting player, they take the starting player marker. -- If they were the starting player, the starting player marker is moved to the player on his left - Advance the Tzolk'in Gear one day. - The player that placed their worker on the Starting Player space may decide to advance the gear one extra day if the player board is light side up AND this advance will not push a player off the gears. -- If you use this option, flip your board to dark side up. -- This does not avoid food days. 27be69f6b48309b7c9910a079900902ff4e52724 Kaozeal:Gamehelpthroughtheages 1 185 1387 2015-03-04T21:34:22Z Tigre azul 7976 Created page with "Durante tu turno, puedes gastar tus acciones en: - recoger cartas de la fila de cartas (si dispones de espacio en tu mano); - jugar las cartas con tu tablero; - au..." wikitext text/x-wiki Durante tu turno, puedes gastar tus acciones en: - recoger cartas de la fila de cartas (si dispones de espacio en tu mano); - jugar las cartas con tu tablero; - aumentar tu población; - construir / mejorar granjas, minas, o edificios urbanos; - construir / mejorar las unidades militares. Los contadores amarillos representan tu población. Pueden estar en uno de los siguientes tres lugares: - en las cartas de tu tablero; - en tu zona de trabajadores disponibles; - en tu "banco amarillo", que cuando esté vacío, significará que ya no se puede aumentar la población disponible. Los contadores azules representan los alimentos o recursos. Pueden estar en dos lugares: - en tus granjas o minas; - en tu "banco azul" - que cuando esté vacío, significará que ya no se puede producir alimentos o recursos. La construcción de tu civilización: - La comida permite mover los trabajadores de tu banco amarillo a tu zona de trabajadores disponibles. - Los recursos permiten mover a los trabajadores de tu zona de trabajadores disponibles a una tarjeta de tu tablero. - La ciencia (bombillas) te permite mover cartas de tu mano a tu tablero. - Cuando tu población crece, tendrás que producir más felicidad o tus trabajadores dejarán de trabajar. - La producción de cultura te hará ganar puntos de victoria. - La producción de fuerza militar te protegerá de ataques o guerras. Hay 3 versiones de Through the Ages: - La simple transcurre a través de las Edades A y I; - La avanzada transcurre a través de las Edades A, I y II, e introduce acciones políticas (colonias y redadas), infelicidad y la corrupción; - La completa a través de las Edades A, I, II y III, e introduce las guerras. En el juego avanzado y completo, se anotan puntos adicionales al final del juego de acuerdo con unas cartas de eventos especiales. Pero al final de la partida simple, los puntos adicionales se adjudican en todas las partidas siempre de la misma manera: - 2 puntos de cultura por cada fuerza militar; - 2 puntos de cultura por cada cara feliz; - 2 puntos de cultura por cada nivel de tecnología en juego; - 1 punto de cultura por cada alimento o recurso producido por turno; - 1 punto de cultura por cada nivel de ciencia (ciencia ganada por turno). 8d4d941d151f008d9229fee3aa184da0e817af1c 1388 1387 2015-03-05T00:30:27Z Tigre azul 7976 Blanked the page wikitext text/x-wiki da39a3ee5e6b4b0d3255bfef95601890afd80709 Gamehelpquantum 0 186 1389 2015-03-07T22:43:15Z Jmaydet 7639 Created page with "Ship Abilities: Each type of ship has a unique special ability that can be used once per turn. * An individual ship die can only use ONE ability per turn, even if it changes ..." wikitext text/x-wiki Ship Abilities: Each type of ship has a unique special ability that can be used once per turn. * An individual ship die can only use ONE ability per turn, even if it changes number. * Using a ship ability does not count as an action (although maneuver and transport are used during a move action). * Ship abilities can only be used on your turn, and only by ships on the map. (Ships in the scrapyard and expansion ships can’t use abilities.) * You cannot change a ship number in the middle of moving that ship - for example, immediately before rolling for combat. 1 (Battlestation) STRIKE: attack space next to the battlestation Strike gives you a single free move/attack of 1 space that must include an attack. It is possible to move/attack normally and also use strike for a second attack on the same turn. 2 (Flagship) TRANSPORT: carry ship as you move Place one of your ships that is in any surrounding space on top of the flagship. Then use the flagship’s move action to move the flagship 1 or 2 spaces. Finally, place the transported ship in any empty surrounding space. A flagship cannot attack if it transports, but a transported ship CAN move and attack normally after it is dropped off. 3 (Destroyer) WARP: swap places with one of your ships on the map Warp does not count as the destroyer’s move 4 (Frigate) MODIFY: change to a 3 or 5 After you modify, you can’t use the ship’s new ability this turn, since modify was the ship’s ability use for the turn 5 (Interceptor) MANEUVER: travel diagonally Activating maneuver during your move action lets you go to any surrounding space as you move. This means you can travel diagonally as part or all of your movement. You CAN attack diagonally. 6 (Scout) FREE RECONFIGURE: re-roll the ship If you roll a 6, roll again until you get a new number. a57a29ed6a6c106455399e33749567a7de21c680 1390 1389 2015-03-07T22:44:31Z Jmaydet 7639 wikitext text/x-wiki Ship Abilities: Each type of ship has a unique special ability that can be used once per turn. * An individual ship die can only use ONE ability per turn, even if it changes number. * Using a ship ability does not count as an action (although maneuver and transport are used during a move action). * Ship abilities can only be used on your turn, and only by ships on the map. (Ships in the scrapyard and expansion ships can’t use abilities.) * You cannot change a ship number in the middle of moving that ship - for example, immediately before rolling for combat. '''1''' (Battlestation) STRIKE: attack space next to the battlestation Strike gives you a single free move/attack of 1 space that must include an attack. It is possible to move/attack normally and also use strike for a second attack on the same turn. '''2''' (Flagship) TRANSPORT: carry ship as you move Place one of your ships that is in any surrounding space on top of the flagship. Then use the flagship’s move action to move the flagship 1 or 2 spaces. Finally, place the transported ship in any empty surrounding space. A flagship cannot attack if it transports, but a transported ship CAN move and attack normally after it is dropped off. '''3''' (Destroyer) WARP: swap places with one of your ships on the map Warp does not count as the destroyer’s move '''4''' (Frigate) MODIFY: change to a 3 or 5 After you modify, you can’t use the ship’s new ability this turn, since modify was the ship’s ability use for the turn '''5''' (Interceptor) MANEUVER: travel diagonally Activating maneuver during your move action lets you go to any surrounding space as you move. This means you can travel diagonally as part or all of your movement. You CAN attack diagonally. '''6''' (Scout) FREE RECONFIGURE: re-roll the ship If you roll a 6, roll again until you get a new number. 6d1223be4106318a616e77f2473518c2c5b7528f Gamehelpcinco 0 187 1392 2015-03-17T05:18:28Z Jest phulin 3510 Creation of page. wikitext text/x-wiki Cinco is a game involving placing tokens to form a straight line of at least 5 places. ==Rules== ===Number of Players=== Cinco can be played with 2, 3, 4 (2 teams of 2 players), or 6 (either 2 teams of 3, or 3 teams of 2) players. It ''cannot'' be played with 5. ===Game Components=== Cinco game components consist of: * a playing board with spaces numbered 1 through 90, inclusive, arranged in a hexagonal continuous path from an empty space at the center of the board. * 90 playing cards, one of each number. * 35 tokens in each of 3 team colors. ===Set-up=== Players are arranged so that alternating teams will take turns. Each player is dealt a hand of 4 cards, which only they are allowed to see. Team members are ''not'' allowed to share information about which cards they hold. ===Turns=== On each turn, players take one of three options: ====Play a card and place a token==== A player will play a card face-up from their hand, and place a token of their color on that number '''or any higher number''', as long as that space is unoccupied. Example 1. Player A reveals the card 68. They may place a token on 68, 69, 70, 71, etc.<br> Example 2. Spaces 87, 88, and 89 are already occupied. Player B reveals the card 87. They may only place a token on space 90.<br> Example 3. Spaces 87, 88, 89, and 90 are already occupied. Player C reveals the card 88. They are unable to place a token. See [[Gamehelpcinco_Joker|Joker Variant]] for a variant to this rule. ====Draw a card==== If the player has fewer than 4 cards in their hand, they may draw 1 new card. ====Exchange a hand of 4 cards==== If the player has exactly 4 cards in their hand, they may discard all 4 cards and draw 4 new ones. ===Running out of cards=== If the draw pile is ever exhausted before the game ends, all discarded cards are reshuffled into a new draw pile. ===Game End=== ====Winning==== The game ends immediately in a win for the ''team'' that places a token that forms a straight line of 5 (or more) pieces of their color. ====Stalemate==== The game ends in a stalemate if one team places their 35th token and nobody has won. ===Variants=== ====Joker==== In the Joker variant, if a card has no legal moves (all spaces of its number and higher are occupied), the card is treated as a "1". Therefore, a token may be placed on any space on the board.<br> Example 1. Spaces 87, 88, and 89 are already occupied. Player A reveals the card 87. They may only place a token on space 90, as it is the only unoccupied space equal to or higher than 87.<br> Example 2. Spaces 87, 88, 89, and 90 are already occupied. Player B reveals the card 88. They may place a token on any unoccupied space, as all space equal to or higher than 88 are occupied. ====6-player game==== In a 6-player game, the game may either be played with 3 teams of 2 players each, or 2 teams of 3 players each. ==External rules links== [http://static.boardgamearena.net/data/others/cincorules.jpg English rules (en)]<br> [http://static.boardgamearena.net/data/others/CINCO-F-quer.jpg Règles du jeu (fr)]<br> [https://www.ptt.cc/bbs/BoardGame/M.1373425968.A.8A0.html Cinco中文教學 (zh) ]<br> [http://static.boardgamearena.net/data/others/CINCO-NL-quer.jpg Reglement (nl)]<br> [http://static.boardgamearena.net/data/others/CINCO-D-quer.jpg Spielregeln (de) ]<br> 29e7e5fff29dcb53b1cf0ad8ffcebf2d440e6adb 1393 1392 2015-03-17T05:21:33Z Jest phulin 3510 wikitext text/x-wiki Cinco is a game involving placing tokens to form a straight line of at least 5 places. ==Rules== ===Number of Players=== Cinco can be played with 2, 3, 4 (2 teams of 2 players), or 6 (either 2 teams of 3, or 3 teams of 2) players. It ''cannot'' be played with 5. ===Game Components=== Cinco game components consist of: * a playing board with spaces numbered 1 through 90, inclusive, arranged in a hexagonal continuous path from an empty space at the center of the board. * 90 playing cards, one of each number. * 35 tokens in each of 3 team colors. ===Set-up=== Players are arranged so that alternating teams will take turns. Each player is dealt a hand of 4 cards, which only they are allowed to see. Team members are ''not'' allowed to share information about which cards they hold. ===Turns=== On each turn, players take one of three options: ====Play a card and place a token==== A player will play a card face-up from their hand, and place a token of their color on that number '''or any higher number''', as long as that space is unoccupied. Example 1. Player A reveals the card 68. They may place a token on 68, 69, 70, 71, etc.<br> Example 2. Spaces 87, 88, and 89 are already occupied. Player B reveals the card 87. They may only place a token on space 90.<br> Example 3. Spaces 87, 88, 89, and 90 are already occupied. Player C reveals the card 88. They are unable to place a token. See [[#Joker|Joker Variant]] for a variant to this rule. ====Draw a card==== If the player has fewer than 4 cards in their hand, they may draw 1 new card. ====Exchange a hand of 4 cards==== If the player has exactly 4 cards in their hand, they may discard all 4 cards and draw 4 new ones. ===Running out of cards=== If the draw pile is ever exhausted before the game ends, all discarded cards are reshuffled into a new draw pile. ===Game End=== ====Winning==== The game ends immediately in a win for the ''team'' that places a token that forms a straight line of 5 (or more) pieces of their color. ====Stalemate==== The game ends in a stalemate if one team places their 35th token and nobody has won. ===Variants=== ====Joker==== In the Joker variant, if a card has no legal moves (all spaces of its number and higher are occupied), the card is treated as a "1". Therefore, a token may be placed on any space on the board.<br> Example 1. Spaces 87, 88, and 89 are already occupied. Player A reveals the card 87. They may only place a token on space 90, as it is the only unoccupied space equal to or higher than 87.<br> Example 2. Spaces 87, 88, 89, and 90 are already occupied. Player B reveals the card 88. They may place a token on any unoccupied space, as all space equal to or higher than 88 are occupied. ====6-player game==== In a 6-player game, the game may either be played with 3 teams of 2 players each, or 2 teams of 3 players each. ==External rules links== [http://static.boardgamearena.net/data/others/cincorules.jpg English rules (en)]<br> [http://static.boardgamearena.net/data/others/CINCO-F-quer.jpg Règles du jeu (fr)]<br> [https://www.ptt.cc/bbs/BoardGame/M.1373425968.A.8A0.html Cinco中文教學 (zh) ]<br> [http://static.boardgamearena.net/data/others/CINCO-NL-quer.jpg Reglement (nl)]<br> [http://static.boardgamearena.net/data/others/CINCO-D-quer.jpg Spielregeln (de) ]<br> d7c8f27d0980eee7220d43bff845f21cd10cbc25 Kaozeal:Gamehelpcinco 1 188 1394 2015-03-17T05:24:11Z Jest phulin 3510 Created page with "Creation of page --~~~~" wikitext text/x-wiki Creation of page --[[User:Jest phulin|Jest phulin]] 06:24, 17 March 2015 (CET) 9c79cbe659aa86d48c258950cb21b43e90ad7dc6 Gamehelpdragonheart 0 31 1395 875 2015-03-21T02:39:16Z Squarerootofthree 5668 /* Cards */ wikitext text/x-wiki ==Summary== Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down. ==Goal== To have the most points by the end of the game. ==Game Start== At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board. ==End== The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 3 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game. In case of a tie, the player with the Great Dragon wins. ==Turns== Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship. ==Cards== There are nine types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it is. Arrows on the board indicate what cards can take what. * ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf. * ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board. * ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards. * ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress. * ''Troll'': Placing this card allows the player to take the sorceress pile. * ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board. * ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent. * ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon. * ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the table. The ship cards are then discarded. The third time that three ship cards are played ends the game and the opponent takes one final turn. * ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand. '''Card Distribution in each deck''' Ships: 6 Treasure chest: 7 - (1,1,2,2,3,3,4) Stone dragon: 5 (2,2,2,2,2) Princess: 4 - (1,1,2,2) Troll 3 - (1,2,3) Dwarf: 10 - (1,1,1,1,1,1,2,2,2,3) Hero: 5 - (1,1,1,1,2) Dragon huntress: 6 - (1,1,1,1,2,2) Fire-dragon: 4 - (2,3,3,4) 438b79564163d14a5bfbba0a4cb1c9e82bf37648 1396 1395 2015-03-21T02:42:04Z Squarerootofthree 5668 /* Cards */ wikitext text/x-wiki ==Summary== Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down. ==Goal== To have the most points by the end of the game. ==Game Start== At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board. ==End== The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 3 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game. In case of a tie, the player with the Great Dragon wins. ==Turns== Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship. ==Cards== There are nine types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it is. Arrows on the board indicate what cards can take what. * ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf. * ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board. * ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards. * ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress. * ''Troll'': Placing this card allows the player to take the sorceress pile. * ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board. * ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent. * ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon. * ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the table. The ship cards are then discarded. The third time that three ship cards are played ends the game and the opponent takes one final turn. * ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then the player gets a random card from the opponents hand. '''Card Distribution in each deck''' * ''Dwarf'': 10 - (1,1,1,1,1,1,2,2,2,3) * ''Huntress'': 6 - (1,1,1,1,2,2) * ''Fire Dragon'': 4 - (2,3,3,4) * ''Treasure Chest'': 7 - (1,1,2,2,3,3,4) * ''Troll'': 3 - (1,2,3) * ''Knight'': 5 - (1,1,1,1,2) * ''Petrified Dragon'': 5 (2,2,2,2,2) * ''Sorceress'': 4 - (1,1,2,2) * ''Ship'': 6 c2f2e942b85296ab87d73785c2ccb4ae5c141394 Gamehelpneutreeko 0 189 1398 2015-03-22T05:56:45Z Cosmosis 6432 Created page with "Movement: A piece slides orthogonally or diagonally until stopped by an occupied square or the border of the board. Black always moves first. Objective: To get three in a row..." wikitext text/x-wiki Movement: A piece slides orthogonally or diagonally until stopped by an occupied square or the border of the board. Black always moves first. Objective: To get three in a row, orthogonally or diagonally. The row must be connected. Repetitions: A match is declared a draw if the same position occurs three times. c3364036eb73a613985eb84ab891f717a0c575ef Gamehelpjaipur 0 115 1399 928 2015-03-23T06:47:23Z Senatorhung 4176 wikitext text/x-wiki In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take. There are 55 goods cards consisting of: * Diamonds x6 * Gold x6 * Silver x6 * Cloth x8 * Spice x8 * Leather x10 * Camels x11 On your turn, you take one of three actions: # '''Take''' a single card or all the camels in the face up row. #: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. #: You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) #: The card row is then replenished from the deck so it always has 5 cards at the start of a turn. # '''Trade''' for 2 or more goods cards from the row. #: You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. #: The cards your traded are added to the card row, so it will still have 5 cards. # '''Sell''' cards to earn points. #: You may sell one or more cards to earn points, but all the cards you sell must be the same color. #: If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. #: Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. #: If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). #: The sold goods cards are discarded. The game continues until either: * Three piles of goods tokens are depleted; OR * The card row cannot be replenished. : At that point, players total the points they have on their earned goods tokens and bonus tokens. : In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. : Whichever player earns more points total wins the round. : Tie-breaker, in order: :* Player with more bonus tokens wins the round; :* Player with more goods tokens wins the round; After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game. 574e9c39f3a45d883b121f78e7dad1efbf6e1070 Gamehelpgearnpiston 0 112 1400 822 2015-03-23T17:11:53Z Squarerootofthree 5668 No longer on Kickstarter so I removed that language and link. wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. **Black Market (draw 3 New Parts and keep 1), **Espionage (look at one player's blueprints and take one of them), **Union Muscle (move an Action Token ahead in another location). *Patent Office: Take 1 New Part, either from the face up parts or from the top of the stack. *Junk Yard: Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (a motor and at least one fuel tank of the same color), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. eae6bf85a6b46c4725cdf7923066e3ff6df43b41 Gamehelpchinagold 0 136 1401 1333 2015-03-23T21:16:56Z Senatorhung 4176 wikitext text/x-wiki A Tactical Dice Game by Günter Cornett for 2 players of 8 years and up (Original Translation: Ben Baldanza) '''What China Gold is about''': Both players are searching for gold, one in the mountains and the other in the rivers. If all the gold of a prospecting area of a mountain or a river is found, the mountain or river player can claim the gold. But note that every prospecting area is at the same moment part of a mountain and part of a river. Thus the players are racing to see who can collect the gold first from each area. '''The Game Board''': 12 mountains, 12 rivers and 61 Prospecting Areas are shown on the game board. The Prospecting Areas are represented both as mountains (brown planes) and as rivers (blue lines). '''Game Play''': On each turn, the sum of the random discs indicates how many Prospecting Area Markers may be turned face up. The Prospecting Area Markers to be turned MUST lie side by side in a straight line, without a gap or previously discovered lumps of gold in between. Instead of turning the thrown number of Prospecting Area Markers face up, the player may hide exactly one nugget again by turning one Prospecting Area Marker face down. When the last marker in one of the player's areas (mountain or river) is turned face up, all of the gold in this area can be claimed. If the last Prospecting Area Marker in one of the opponent's areas is turned face up at the same time, the opponent then claims the gold in this area. '''Small Disc Reduction''': Five not yet turned Prospecting Area Markers in a straight line make two different possibilities to turn four Prospecting Area Markers face up. When there is at most one straight line of five Prospecting Area Markers neighboring in straight line that could be turned face up, the small disc 0/1 is returned to the box. For the remainder of the game, small discs 0/2 and 1/2 will be used so that only numbers from 1 to 4 will be available. Four not yet turned Prospecting Area Markers in a straight line make two different possibilities to turn three Prospecting Area Markers face up. When there is at most one straight line of four Prospecting Area Markers neighboring in straight line that could be turned face up, the small disc 0/2 is replaced with the small disc 0/1 from the box so that only numbers from 1to 3 will be available. When there is at most one straight line of three Prospecting Area Markers neighboring in straight line that could be turned face up, all small discs are returned to the box. From now on the players may choose between turning a single or two neighbouring Prospecting Area Markers face up. If turning back a Prospecting Area Marker creates a situation with more possibilities to turn free Prospecting Area Markers in straight line face up, the appropriate number of small discs is used. '''Game End''': When all Prospecting Areas are cleared, the player who collected the most gold is the winner ! 91631bd3486379bb360f55054f92cf1a45252065 Gamehelpchinagold 0 136 1402 1401 2015-03-23T21:17:52Z Senatorhung 4176 wikitext text/x-wiki A Tactical Dice Game by Günter Cornett for 2 players of 8 years and up (Original Translation: Ben Baldanza) '''What China Gold is about''': Both players are searching for gold, one in the mountains and the other in the rivers. If all the gold of a prospecting area of a mountain or a river is found, the mountain or river player can claim the gold. But note that every prospecting area is at the same moment part of a mountain and part of a river. Thus the players are racing to see who can collect the gold first from each area. '''The Game Board''': 12 mountains, 12 rivers and 61 Prospecting Areas are shown on the game board. The Prospecting Areas are represented both as mountains (brown planes) and as rivers (blue lines). '''Game Play''': On each turn, the sum of the random discs indicates how many Prospecting Area Markers may be turned face up. The Prospecting Area Markers to be turned MUST lie side by side in a straight line, without a gap or previously discovered lumps of gold in between. Instead of turning the thrown number of Prospecting Area Markers face up, the player may hide exactly one nugget again by turning one Prospecting Area Marker face down. When the last marker in one of the player's areas (mountain or river) is turned face up, all of the gold in this area can be claimed. If the last Prospecting Area Marker in one of the opponent's areas is turned face up at the same time, the opponent then claims the gold in this area. '''Small Disc Reduction''': Five not yet turned Prospecting Area Markers in a straight line make two different possibilities to turn four Prospecting Area Markers face up. When there is at most one straight line of five Prospecting Area Markers neighboring in straight line that could be turned face up, the small disc 0/1 is returned to the box. For the remainder of the game, small discs 0/2 and 1/2 will be used so that only numbers from 1 to 4 will be available. Four not yet turned Prospecting Area Markers in a straight line make two different possibilities to turn three Prospecting Area Markers face up. When there is at most one straight line of four Prospecting Area Markers neighboring in straight line that could be turned face up, the small disc 0/2 is replaced with the small disc 0/1 from the box so that only numbers from 1 to 3 will be available. When there is at most one straight line of three Prospecting Area Markers neighboring in straight line that could be turned face up, all small discs are returned to the box. From now on the players may choose between turning a single or two neighbouring Prospecting Area Markers face up. If turning back a Prospecting Area Marker creates a situation with more possibilities to turn free Prospecting Area Markers in straight line face up, the appropriate number of small discs is used. '''Game End''': When all Prospecting Areas are cleared, the player who collected the most gold is the winner ! f00fcd1be10a9f45de536ecaea4b50b147529d5b 1403 1402 2015-03-23T21:18:18Z Senatorhung 4176 wikitext text/x-wiki A Tactical Dice Game by Günter Cornett for 2 players of 8 years and up (Original Translation: Ben Baldanza) '''What China Gold is about''': Both players are searching for gold, one in the mountains and the other in the rivers. If all the gold of a prospecting area of a mountain or a river is found, the mountain or river player can claim the gold. But note that every prospecting area is at the same moment part of a mountain and part of a river. Thus the players are racing to see who can collect the gold first from each area. '''The Game Board''': 12 mountains, 12 rivers and 61 Prospecting Areas are shown on the game board. The Prospecting Areas are represented both as mountains (brown planes) and as rivers (blue lines). '''Game Play''': On each turn, the sum of the random discs indicates how many Prospecting Area Markers may be turned face up. The Prospecting Area Markers to be turned MUST lie side by side in a straight line, without a gap or previously discovered lumps of gold in between. Instead of turning the thrown number of Prospecting Area Markers face up, the player may hide exactly one nugget again by turning one Prospecting Area Marker face down. When the last marker in one of the player's areas (mountain or river) is turned face up, all of the gold in this area can be claimed. If the last Prospecting Area Marker in one of the opponent's areas is turned face up at the same time, the opponent then claims the gold in this area. '''Small Disc Reduction''': Five not yet turned Prospecting Area Markers in a straight line make two different possibilities to turn four Prospecting Area Markers face up. When there is at most one straight line of five Prospecting Area Markers neighboring in straight line that could be turned face up, the small disc 0/1 is returned to the box. For the remainder of the game, small discs 0/2 and 1/2 will be used so that only numbers from 1 to 4 will be available. Four not yet turned Prospecting Area Markers in a straight line make two different possibilities to turn three Prospecting Area Markers face up. When there is at most one straight line of four Prospecting Area Markers neighboring in straight line that could be turned face up, the small disc 0/2 is replaced with the small disc 0/1 from the box so that only numbers from 1 to 3 will be available. When there is at most one straight line of three Prospecting Area Markers neighboring in straight line that could be turned face up, all small discs are returned to the box. From now on the players may choose between turning a single or two neighbouring Prospecting Area Markers face up. If turning back a Prospecting Area Marker creates a situation with more possibilities to turn free Prospecting Area Markers in straight line face up, the appropriate number of small discs is used. '''Game End''': When all Prospecting Areas are cleared, the player who collected the most gold is the winner ! 93719f2588b3c9fa59de136c2a6759f34cdd169a Gamehelpk2 0 184 1404 1397 2015-03-25T07:30:57Z Ice82 8420 wikitext text/x-wiki '''Turn Summary''' <ol> <li>'''Card Selection'''</li> <ol> <li>Each player plays 3 cards face down.</li> <li>Players reveal them simultaneously.</li> </ol> <li>'''Risk Tokens'''</li> <ol> <li>The player with the most movement points takes a risk token. In case of a tie, no one takes a risk token.</li> <li>Another risk token is revealed if needed.</li> </ol> <li>'''Action Phase'''</li> <ol> <li>Players move their climbers using their played (green) cards.</li> <li>Placing a tent costs the same as the cost to enter that space.</li> <li>Players increase their climbers' acclimatization level using their played (blue) cards.</li> <li>The player with a risk token must suffer the consequences and either reduce their movement by that amount or, if they choose not to, subtract acclimatization points from a climber who had one or more cards assigned to this turn.</li> <li>Each climber's newly gained victory points are marked on the victory point track.</li> <li>Note the influence of weather on movement (only in winter weather)!.</li> </ol> <li>'''Acclimatization Checks'''</li> <ol> <li>Add/subtract acclimatization according to each climber's current space.</li> <li>A tent adds +1 to acclimatization.</li> <li>Subtract acclimatization resulting from the current weather, if in the affected altitude zone.</li> <li>If acclimatization exceeds 6, it is reduced back to 6.</li> <li>If acclimatization drops below 1, the climber dies and losing any VP gained.</li> </ol> <li>'''End of Turn'''</li> <ol> <li>The starting player marker passes to the left.</li> <li>The weather marker moves to the next space.</li> <li>Draw 3 cards to have 6 again.</li> </ol> </ol> '''FINE DEL GIOCO''' Il gioco termina '''alla fine del diciottesimo giorno''', quando tutte le tessere meteo sono state esaurite. Il giocatore che ha accumulato la '''somma maggiore di punti vittoria dai propri alpinisti''' sarà proclamato vincitore. '''In caso di parità''' il vincitore è colui il cui alpinista (tra quelli a parità di punti) '''ha raggiunto per primo la vetta'''. 022e6047f05907d2cee3bf6fd6ed5d4c42f34a8a 1405 1404 2015-03-25T14:21:00Z Ice82 8420 wikitext text/x-wiki '''Turn Summary''' <ol> <li>'''Card Selection'''</li> <ol> <li>Each player plays 3 cards face down.</li> <li>Players reveal them simultaneously.</li> </ol> <li>'''Risk Tokens'''</li> <ol> <li>The player with the most movement points takes a risk token. In case of a tie, no one takes a risk token.</li> <li>Another risk token is revealed if needed.</li> </ol> <li>'''Action Phase'''</li> <ol> <li>Players move their climbers using their played (green) cards.</li> <li>Placing a tent costs the same as the cost to enter that space.</li> <li>Players increase their climbers' acclimatization level using their played (blue) cards.</li> <li>The player with a risk token must suffer the consequences and either reduce their movement by that amount or, if they choose not to, subtract acclimatization points from a climber who had one or more cards assigned to this turn.</li> <li>Each climber's newly gained victory points are marked on the victory point track.</li> <li>Note the influence of weather on movement (only in winter weather)!.</li> </ol> <li>'''Acclimatization Checks'''</li> <ol> <li>Add/subtract acclimatization according to each climber's current space.</li> <li>A tent adds +1 to acclimatization.</li> <li>Subtract acclimatization resulting from the current weather, if in the affected altitude zone.</li> <li>If acclimatization exceeds 6, it is reduced back to 6.</li> <li>If acclimatization drops below 1, the climber dies and losing any VP gained.</li> </ol> <li>'''End of Turn'''</li> <ol> <li>The starting player marker passes to the left.</li> <li>The weather marker moves to the next space.</li> <li>Draw 3 cards to have 6 again.</li> </ol> </ol> 5a59321c7a86312580697f80f347f4ef34ea7dd3 1411 1405 2015-03-30T16:16:06Z Spamymaps 5732 wikitext text/x-wiki '''Turn Summary''' <ol> <li>'''Card Selection'''</li> <ol> <li>Each player plays 3 cards face down.</li> <li>Players reveal them simultaneously.</li> </ol> <li>'''Risk Tokens'''</li> <ol> <li>The player with the most movement points takes a risk token. In case of a tie, no one takes a risk token.</li> <li>Another risk token is revealed if needed.</li> </ol> <li>'''Action Phase'''</li> <ol> <li>Players move their climbers using their played (green) cards.</li> <li>Placing a tent costs the same as the cost to enter that space.</li> <li>Players increase their climbers' acclimatization level using their played (blue) cards.</li> <li>The player with a risk token must suffer the consequences and either reduce their movement by that amount or, if they choose not to, subtract acclimatization points from a climber who had one or more cards assigned to this turn.</li> <li>Each climber's newly gained victory points are marked on the victory point track.</li> <li>Note the influence of weather on movement (only in winter weather)!.</li> </ol> <li>'''Acclimatization Checks'''</li> <ol> <li>Add/subtract acclimatization according to each climber's current space.</li> <li>A tent of the player's color adds +1 to acclimatization.</li> <li>Subtract acclimatization resulting from the current weather, if in the affected altitude zone.</li> <li>If acclimatization exceeds 6, it is reduced back to 6.</li> <li>If acclimatization drops below 1, the climber dies and losing any VP gained.</li> </ol> <li>'''End of Turn'''</li> <ol> <li>The starting player marker passes to the left.</li> <li>The weather marker moves to the next space.</li> <li>Draw 3 cards to have 6 again.</li> </ol> </ol> 331f98f845ffa46308c062650571b32897deea85 Gamehelptargi 0 169 1406 1183 2015-03-26T22:57:04Z Bkunes 4384 Removed a duplicate "may" in the description of the third stage. wikitext text/x-wiki Each round of play has the following stages: # Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column as your opponent's Targi. # Place 1 or 2 "tribal markers" in the middle of the game board at the intersection of the rows/columns of your targi. # You may then activate the cards under each of your pieces. These cards may give you more goods, or they may let you spend your goods to purchase special cards to place in your personal tableau. You may only hold 3 gold and 10 goods total between rounds. The game ends when a player has filled their tableau, or when the robber has completed one jog around the map. In addition to the victory points earned during the game and from special card abilities, you also get: * 4 victory points for a building a row of identical cards in your tableau, and * 2 victory points for a row of all different cards ef10617beccf314c5918ba24f45e64085dbbb879 Gamehelpsaboteur 0 32 1407 1374 2015-03-27T07:28:50Z Wiccaesar 8438 Correction: if you are a saboteur, you must, in association with other saboteurs (PREVIOUSLY GOLD DIGGERS), prevent the gold diggers to get to the treasure. wikitext text/x-wiki == Goal == Get as many gold nuggets as possible during the three rounds of the game. In order to do so, # if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards # if you are a '''saboteur''', you must, in association with other saboteurs, prevent the gold diggers to get to the treasure. Your role (gold digger or saboteur) will be randomly selected at the start of each round. == Rules summary == On your turn, you must click on a card from your hand to select it, then play this card or discard it. You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card. The cards are of several types: * 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card. * 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score). A player with a broken tool cannot play a Path card. * 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you. * 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know everything about. * 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove. == Cards in play == * 44 'Path' cards * 9 'Sabotage' cards (three for each tool) * 6 'Repair a tool' cards (two for each tool) * 3 'Repair a tool among these two' cards (one for each combination of two tools) * 5 'Map' cards (one less than in the box set, as requested by the game author) * 3 'Rock fall' cards * 28 'Gold' cards ** 16 with one gold nugget ** 8 with two gold nuggets ** 4 with three gold nuggets == Roles == Roles are randomly selected among a set that depends upon the number of players: * with 3 players: 1 saboteur and 3 gold diggers * with 4 players: 1 saboteur and 4 gold diggers * with 5 players: 2 saboteurs and 4 gold diggers * with 6 players: 2 saboteurs and 5 gold diggers * with 7 players: 3 saboteurs and 5 gold diggers * with 8 players: 3 saboteurs and 6 gold diggers * with 9 players: 3 saboteurs and 7 gold diggers * with 10 players: 4 saboteurs and 7 gold diggers == Available variants == The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum! '''Have a good game !''' ff89f68dfdb5ec6ee91a6171199cb948bd888097 Gamehelpsobek 0 166 1408 1187 2015-03-30T05:49:08Z 340427770 8471 /* Theme */ wikitext text/x-wiki ==遊戲簡介== 遊戲簡介】供奉索貝克神廟的工程已經如火如荼的建造當中。一個全面的經濟體系已在施工現場旁成立:有一個新的市場,並且有帆船在尼羅河上下航行,不斷帶來各種商品。商家之間的競爭自然激烈,有些商家為了累計更多的榮耀和財富已經開始變得腐敗。主要的財富,其實您也是屬於當地商人的行會,並準備盡全力代價打敗你的對手... 在3輪中比你的對手獲得更多的錢,但盡量不要太腐敗! ==Game turns and actions== On your turn you must choose one of the 3 actions. Then play passes to the player on your left. The actions are: * '''Take a card from the marketplace and add it to your hand''' : Only the first four cards (starting from the left) are available. Taking the first available card has no consequences since the order of arrival of the feluccas is respected. However, taking one of the other cards causes corruption. All the cards that you skip end up in your corruption pile. * '''Play a character card and apply its power''' : See below for powers. * '''Play a set''' : A set is a group of at least three goods cards of the same type. A set can include one or more amulets which act as wild cards (jokers). A set can also include characters - each character is associated with a goods type; this is shown on the card. When a character is played as part of a set, its power is ignored. : It is possible to add cards to a set that has already been played (in order to earn more points during scoring), but the same rule still applies: you must add a minimum of 3 new cards. : When a set is played an event are triggered (provided at least 1 of the 5 event tokens remains). The player who played the set chooses an event from the remaining tokens and immediately applies its effect. The token is then discarded. ==Event tokens== There are 12 event tokens with 5 randomly selected for each round: * 4 x Guild - (one of each of snake, reed, ankh, scorpion). On the scoring track, move your scoring marker forward to the next space of that symbol and move an opponent's scoring marker back to the next space of that symbol. * 2 x Flood - Take another turn * 2 x Curse - Add a curse token to another player's corruption pile; it counts as 2 cards in that player's pile. * 2 x Prosperity - add the token to one of your fish, cattle or wheat sets, thus increasing the score of this set. * 1 x Embalming - return all the cards from your corruption pile to your hand * 1 x Deceit - Score the number of cards in your corruption pile ==Character cards== * 1 x Queen Sobek Neferou - draw 3 cards and add them to your hand. * 2 x High Priest/Priestess - discard all the cards of one goods type from your corruption pile. Characters of that goods type can be discarded. Amulets (wild cards) cannot be discarded. * 2 x Scribe - your opponents reduce their hands down to 6 cards; the remainder are added to their corruption pile. * 1 x Vizir - add a card of your choice to your hand from an opponent's corruption pile. * 1 x Courtesan - add 1 or 2 cards from your hand to an existing played set. * 1 x Thief - steal a card from an opponent. You can see the different coloured backs of the card so you know which type of card you are stealing. ==Goods cards== There are 54 goods cards in total: :6 x Ivory :7 x Ebony :7 x Marble :9 x Cattle :10 x Fish :10 x Wheat :5 x Amulet Nine of the cards have a different coloured back; the player's starting hand is dealt from these leaving 45 cards which are shuffled with the character cards to form the deck. In a two player game 9 cards are removed at random so there will be only 5 goods deliveries not 6 as normal. ==End of the round== The round ends and is scored when the last card is taken from the marketplace. Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand. You cannot play character cards; you cannot add to existing sets. All cards remaining in the players hand are added to their corruption pile. Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs. Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols. == Game end == The game ends after 3 rounds. The game can end early if one player gets more than 100 points. 52d79bb44eaa46c71dd2bd6c51f06822493be769 1409 1408 2015-03-30T05:50:13Z 340427770 8471 /* Game turns and actions */ wikitext text/x-wiki ==遊戲簡介== 遊戲簡介】供奉索貝克神廟的工程已經如火如荼的建造當中。一個全面的經濟體系已在施工現場旁成立:有一個新的市場,並且有帆船在尼羅河上下航行,不斷帶來各種商品。商家之間的競爭自然激烈,有些商家為了累計更多的榮耀和財富已經開始變得腐敗。主要的財富,其實您也是屬於當地商人的行會,並準備盡全力代價打敗你的對手... 在3輪中比你的對手獲得更多的錢,但盡量不要太腐敗! 玩家流程】一開始綠色牌背的卡每個人發兩張。 輪到你的時候,有以下三擇一選項: 1.拿一張卡(從岸邊選一個停靠的船) 2.出一張人物卡(使用卡片上的功能,或者當棄牌使用) 3.打一組牌(三個一樣為一組) 你的回合結束之後就換你左邊的玩家進行挑選三個行動,然後再換下一家,依此類推。 結束】當牌堆被拿完,第一輪結束,遊戲將進行三輪。 打出來的牌上面會有分數計算,分數高的為優勝。 心得】此款遊戲設計者也設計了其它多款有名的遊戲,像圓桌武士、Mr.Jack,牙買加,群島爭霸...等。這一款遊戲也算是小品遊戲,但中間不乏有策略、運氣成分。 玩起來節奏也快,不會拖臺錢,算是CP值很高的遊戲。 另外一個值得推薦的地方就是它的美工設計,連內盒都設計很漂亮,真是個好遊戲! 卡牌屋全彩規則也為大家準備好了,讓你輕鬆上手沒煩惱。 ==Event tokens== There are 12 event tokens with 5 randomly selected for each round: * 4 x Guild - (one of each of snake, reed, ankh, scorpion). On the scoring track, move your scoring marker forward to the next space of that symbol and move an opponent's scoring marker back to the next space of that symbol. * 2 x Flood - Take another turn * 2 x Curse - Add a curse token to another player's corruption pile; it counts as 2 cards in that player's pile. * 2 x Prosperity - add the token to one of your fish, cattle or wheat sets, thus increasing the score of this set. * 1 x Embalming - return all the cards from your corruption pile to your hand * 1 x Deceit - Score the number of cards in your corruption pile ==Character cards== * 1 x Queen Sobek Neferou - draw 3 cards and add them to your hand. * 2 x High Priest/Priestess - discard all the cards of one goods type from your corruption pile. Characters of that goods type can be discarded. Amulets (wild cards) cannot be discarded. * 2 x Scribe - your opponents reduce their hands down to 6 cards; the remainder are added to their corruption pile. * 1 x Vizir - add a card of your choice to your hand from an opponent's corruption pile. * 1 x Courtesan - add 1 or 2 cards from your hand to an existing played set. * 1 x Thief - steal a card from an opponent. You can see the different coloured backs of the card so you know which type of card you are stealing. ==Goods cards== There are 54 goods cards in total: :6 x Ivory :7 x Ebony :7 x Marble :9 x Cattle :10 x Fish :10 x Wheat :5 x Amulet Nine of the cards have a different coloured back; the player's starting hand is dealt from these leaving 45 cards which are shuffled with the character cards to form the deck. In a two player game 9 cards are removed at random so there will be only 5 goods deliveries not 6 as normal. ==End of the round== The round ends and is scored when the last card is taken from the marketplace. Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand. You cannot play character cards; you cannot add to existing sets. All cards remaining in the players hand are added to their corruption pile. Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs. Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols. == Game end == The game ends after 3 rounds. The game can end early if one player gets more than 100 points. 56e58536866cb4e5ca5331f28f5986c5a79752e6 1410 1409 2015-03-30T05:54:20Z 340427770 8471 /* Goods cards */ wikitext text/x-wiki ==遊戲簡介== 遊戲簡介】供奉索貝克神廟的工程已經如火如荼的建造當中。一個全面的經濟體系已在施工現場旁成立:有一個新的市場,並且有帆船在尼羅河上下航行,不斷帶來各種商品。商家之間的競爭自然激烈,有些商家為了累計更多的榮耀和財富已經開始變得腐敗。主要的財富,其實您也是屬於當地商人的行會,並準備盡全力代價打敗你的對手... 在3輪中比你的對手獲得更多的錢,但盡量不要太腐敗! 玩家流程】一開始綠色牌背的卡每個人發兩張。 輪到你的時候,有以下三擇一選項: 1.拿一張卡(從岸邊選一個停靠的船) 2.出一張人物卡(使用卡片上的功能,或者當棄牌使用) 3.打一組牌(三個一樣為一組) 你的回合結束之後就換你左邊的玩家進行挑選三個行動,然後再換下一家,依此類推。 結束】當牌堆被拿完,第一輪結束,遊戲將進行三輪。 打出來的牌上面會有分數計算,分數高的為優勝。 心得】此款遊戲設計者也設計了其它多款有名的遊戲,像圓桌武士、Mr.Jack,牙買加,群島爭霸...等。這一款遊戲也算是小品遊戲,但中間不乏有策略、運氣成分。 玩起來節奏也快,不會拖臺錢,算是CP值很高的遊戲。 另外一個值得推薦的地方就是它的美工設計,連內盒都設計很漂亮,真是個好遊戲! 卡牌屋全彩規則也為大家準備好了,讓你輕鬆上手沒煩惱。 ==Event tokens== There are 12 event tokens with 5 randomly selected for each round: * 4 x Guild - (one of each of snake, reed, ankh, scorpion). On the scoring track, move your scoring marker forward to the next space of that symbol and move an opponent's scoring marker back to the next space of that symbol. * 2 x Flood - Take another turn * 2 x Curse - Add a curse token to another player's corruption pile; it counts as 2 cards in that player's pile. * 2 x Prosperity - add the token to one of your fish, cattle or wheat sets, thus increasing the score of this set. * 1 x Embalming - return all the cards from your corruption pile to your hand * 1 x Deceit - Score the number of cards in your corruption pile ==Character cards== * 1 x Queen Sobek Neferou - draw 3 cards and add them to your hand. * 2 x High Priest/Priestess - discard all the cards of one goods type from your corruption pile. Characters of that goods type can be discarded. Amulets (wild cards) cannot be discarded. * 2 x Scribe - your opponents reduce their hands down to 6 cards; the remainder are added to their corruption pile. * 1 x Vizir - add a card of your choice to your hand from an opponent's corruption pile. * 1 x Courtesan - add 1 or 2 cards from your hand to an existing played set. * 1 x Thief - steal a card from an opponent. You can see the different coloured backs of the card so you know which type of card you are stealing. 货物卡 There are in总:54货物卡 6×象牙 7×乌木 7×大理石 9×牛 10×鱼 10×小麦 5×护身符 Nine of the cards have a different coloured back; the player's starting hand is dealt from these leaving 45 cards which are shuffled with the character cards to form the deck. In a two player game 9 cards are removed at random so there will be only 5 goods deliveries not 6 as normal. ==End of the round== The round ends and is scored when the last card is taken from the marketplace. Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand. You cannot play character cards; you cannot add to existing sets. All cards remaining in the players hand are added to their corruption pile. Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs. Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols. == Game end == The game ends after 3 rounds. The game can end early if one player gets more than 100 points. c347ab4cb6d43b9405aa5e52a7df59dda02c9372 1414 1410 2015-04-02T11:01:11Z 340427770 8471 /* Event tokens */ wikitext text/x-wiki ==遊戲簡介== 遊戲簡介】供奉索貝克神廟的工程已經如火如荼的建造當中。一個全面的經濟體系已在施工現場旁成立:有一個新的市場,並且有帆船在尼羅河上下航行,不斷帶來各種商品。商家之間的競爭自然激烈,有些商家為了累計更多的榮耀和財富已經開始變得腐敗。主要的財富,其實您也是屬於當地商人的行會,並準備盡全力代價打敗你的對手... 在3輪中比你的對手獲得更多的錢,但盡量不要太腐敗! 玩家流程】一開始綠色牌背的卡每個人發兩張。 輪到你的時候,有以下三擇一選項: 1.拿一張卡(從岸邊選一個停靠的船) 2.出一張人物卡(使用卡片上的功能,或者當棄牌使用) 3.打一組牌(三個一樣為一組) 你的回合結束之後就換你左邊的玩家進行挑選三個行動,然後再換下一家,依此類推。 結束】當牌堆被拿完,第一輪結束,遊戲將進行三輪。 打出來的牌上面會有分數計算,分數高的為優勝。 心得】此款遊戲設計者也設計了其它多款有名的遊戲,像圓桌武士、Mr.Jack,牙買加,群島爭霸...等。這一款遊戲也算是小品遊戲,但中間不乏有策略、運氣成分。 玩起來節奏也快,不會拖臺錢,算是CP值很高的遊戲。 另外一個值得推薦的地方就是它的美工設計,連內盒都設計很漂亮,真是個好遊戲! 卡牌屋全彩規則也為大家準備好了,讓你輕鬆上手沒煩惱。 ==Event tokens== 守卫x4:你的计分标记马上前进到下一个该符号的地方,并且选择一个对手,他的计分标记后退到前一个该符号的地方。(这四个事件在游戏二、三轮比较强力,各只有1个)。 繁殖x2:选择你一个在场的牛、鱼、小麦组合,放置该标记,该组合这轮结束多两个甲虫。 绿洲x2:额外奖励一个行动(送一个回合,马上执行)。(中规中矩) 诈骗x1:在你的黑锅里有多少张牌,马上加多少分。(表面没啥用,其实。。。) 诅咒x2:把该标志送给一个对手,在计算爆锅的时候,他的黑锅算多有两张牌。 复活x1:马上把你黑锅里的所有卡牌加入手牌。(游戏后期最强事件,要啥有啥…) ==Character cards== * 1 x Queen Sobek Neferou - draw 3 cards and add them to your hand. * 2 x High Priest/Priestess - discard all the cards of one goods type from your corruption pile. Characters of that goods type can be discarded. Amulets (wild cards) cannot be discarded. * 2 x Scribe - your opponents reduce their hands down to 6 cards; the remainder are added to their corruption pile. * 1 x Vizir - add a card of your choice to your hand from an opponent's corruption pile. * 1 x Courtesan - add 1 or 2 cards from your hand to an existing played set. * 1 x Thief - steal a card from an opponent. You can see the different coloured backs of the card so you know which type of card you are stealing. 货物卡 There are in总:54货物卡 6×象牙 7×乌木 7×大理石 9×牛 10×鱼 10×小麦 5×护身符 Nine of the cards have a different coloured back; the player's starting hand is dealt from these leaving 45 cards which are shuffled with the character cards to form the deck. In a two player game 9 cards are removed at random so there will be only 5 goods deliveries not 6 as normal. ==End of the round== The round ends and is scored when the last card is taken from the marketplace. Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand. You cannot play character cards; you cannot add to existing sets. All cards remaining in the players hand are added to their corruption pile. Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs. Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols. == Game end == The game ends after 3 rounds. The game can end early if one player gets more than 100 points. 2859edfee6ef36164bd2ae4c01a0414120f5b557 1415 1414 2015-04-02T11:03:00Z 340427770 8471 /* Character cards */ wikitext text/x-wiki ==遊戲簡介== 遊戲簡介】供奉索貝克神廟的工程已經如火如荼的建造當中。一個全面的經濟體系已在施工現場旁成立:有一個新的市場,並且有帆船在尼羅河上下航行,不斷帶來各種商品。商家之間的競爭自然激烈,有些商家為了累計更多的榮耀和財富已經開始變得腐敗。主要的財富,其實您也是屬於當地商人的行會,並準備盡全力代價打敗你的對手... 在3輪中比你的對手獲得更多的錢,但盡量不要太腐敗! 玩家流程】一開始綠色牌背的卡每個人發兩張。 輪到你的時候,有以下三擇一選項: 1.拿一張卡(從岸邊選一個停靠的船) 2.出一張人物卡(使用卡片上的功能,或者當棄牌使用) 3.打一組牌(三個一樣為一組) 你的回合結束之後就換你左邊的玩家進行挑選三個行動,然後再換下一家,依此類推。 結束】當牌堆被拿完,第一輪結束,遊戲將進行三輪。 打出來的牌上面會有分數計算,分數高的為優勝。 心得】此款遊戲設計者也設計了其它多款有名的遊戲,像圓桌武士、Mr.Jack,牙買加,群島爭霸...等。這一款遊戲也算是小品遊戲,但中間不乏有策略、運氣成分。 玩起來節奏也快,不會拖臺錢,算是CP值很高的遊戲。 另外一個值得推薦的地方就是它的美工設計,連內盒都設計很漂亮,真是個好遊戲! 卡牌屋全彩規則也為大家準備好了,讓你輕鬆上手沒煩惱。 ==Event tokens== 守卫x4:你的计分标记马上前进到下一个该符号的地方,并且选择一个对手,他的计分标记后退到前一个该符号的地方。(这四个事件在游戏二、三轮比较强力,各只有1个)。 繁殖x2:选择你一个在场的牛、鱼、小麦组合,放置该标记,该组合这轮结束多两个甲虫。 绿洲x2:额外奖励一个行动(送一个回合,马上执行)。(中规中矩) 诈骗x1:在你的黑锅里有多少张牌,马上加多少分。(表面没啥用,其实。。。) 诅咒x2:把该标志送给一个对手,在计算爆锅的时候,他的黑锅算多有两张牌。 复活x1:马上把你黑锅里的所有卡牌加入手牌。(游戏后期最强事件,要啥有啥…) 人物: 女祭司:马上把你黑锅同种类型的牌全部丢弃。(含人物牌,不能丢弃百搭牌) 女王:马上从牌堆抽3张牌。(会让最后一次补牌变成6张) 挖坟:选择一个对方的黑锅,看里面所有牌并拿一张上手。 商人:从桌面上选择一张卡牌加入手牌,无视4选1规则并且不会得到弃牌到黑锅的惩罚。 男祭祀:同女祭司。 书记官:其他玩家马上把手牌丢弃到剩下6张,丢弃的牌全进入各自的黑锅。 小偷:随机偷一个对手的手牌一张,但是可以看牌背颜色。(所以偷人物牌一定能偷到) 史记官:同书记官。 大臣:你可以选择一个自己已打出的组合,在上面放对应的1~2张货物扩大组合。(不会被卡) 货物卡 There are in总:54货物卡 6×象牙 7×乌木 7×大理石 9×牛 10×鱼 10×小麦 5×护身符 Nine of the cards have a different coloured back; the player's starting hand is dealt from these leaving 45 cards which are shuffled with the character cards to form the deck. In a two player game 9 cards are removed at random so there will be only 5 goods deliveries not 6 as normal. ==End of the round== The round ends and is scored when the last card is taken from the marketplace. Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand. You cannot play character cards; you cannot add to existing sets. All cards remaining in the players hand are added to their corruption pile. Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs. Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols. == Game end == The game ends after 3 rounds. The game can end early if one player gets more than 100 points. 5603766a0d88477c62f5c28eb8226529c564fc83 1416 1415 2015-04-02T11:05:08Z 340427770 8471 /* Event tokens */ wikitext text/x-wiki ==遊戲簡介== 遊戲簡介】供奉索貝克神廟的工程已經如火如荼的建造當中。一個全面的經濟體系已在施工現場旁成立:有一個新的市場,並且有帆船在尼羅河上下航行,不斷帶來各種商品。商家之間的競爭自然激烈,有些商家為了累計更多的榮耀和財富已經開始變得腐敗。主要的財富,其實您也是屬於當地商人的行會,並準備盡全力代價打敗你的對手... 在3輪中比你的對手獲得更多的錢,但盡量不要太腐敗! 玩家流程】一開始綠色牌背的卡每個人發兩張。 輪到你的時候,有以下三擇一選項: 1.拿一張卡(從岸邊選一個停靠的船) 2.出一張人物卡(使用卡片上的功能,或者當棄牌使用) 3.打一組牌(三個一樣為一組) 你的回合結束之後就換你左邊的玩家進行挑選三個行動,然後再換下一家,依此類推。 結束】當牌堆被拿完,第一輪結束,遊戲將進行三輪。 打出來的牌上面會有分數計算,分數高的為優勝。 心得】此款遊戲設計者也設計了其它多款有名的遊戲,像圓桌武士、Mr.Jack,牙買加,群島爭霸...等。這一款遊戲也算是小品遊戲,但中間不乏有策略、運氣成分。 玩起來節奏也快,不會拖臺錢,算是CP值很高的遊戲。 另外一個值得推薦的地方就是它的美工設計,連內盒都設計很漂亮,真是個好遊戲! 卡牌屋全彩規則也為大家準備好了,讓你輕鬆上手沒煩惱。 == 卡牌与人物牌介绍 == 守卫x4:你的计分标记马上前进到下一个该符号的地方,并且选择一个对手,他的计分标记后退到前一个该符号的地方。(这四个事件在游戏二、三轮比较强力,各只有1个)。 繁殖x2:选择你一个在场的牛、鱼、小麦组合,放置该标记,该组合这轮结束多两个甲虫。 绿洲x2:额外奖励一个行动(送一个回合,马上执行)。(中规中矩) 诈骗x1:在你的黑锅里有多少张牌,马上加多少分。(表面没啥用,其实。。。) 诅咒x2:把该标志送给一个对手,在计算爆锅的时候,他的黑锅算多有两张牌。 复活x1:马上把你黑锅里的所有卡牌加入手牌。(游戏后期最强事件,要啥有啥…) 人物: 女祭司:马上把你黑锅同种类型的牌全部丢弃。(含人物牌,不能丢弃百搭牌) 女王:马上从牌堆抽3张牌。(会让最后一次补牌变成6张) 挖坟:选择一个对方的黑锅,看里面所有牌并拿一张上手。 商人:从桌面上选择一张卡牌加入手牌,无视4选1规则并且不会得到弃牌到黑锅的惩罚。 男祭祀:同女祭司。 书记官:其他玩家马上把手牌丢弃到剩下6张,丢弃的牌全进入各自的黑锅。 小偷:随机偷一个对手的手牌一张,但是可以看牌背颜色。(所以偷人物牌一定能偷到) 史记官:同书记官。 大臣:你可以选择一个自己已打出的组合,在上面放对应的1~2张货物扩大组合。(不会被卡) 货物卡 There are in总:54货物卡 6×象牙 7×乌木 7×大理石 9×牛 10×鱼 10×小麦 5×护身符 Nine of the cards have a different coloured back; the player's starting hand is dealt from these leaving 45 cards which are shuffled with the character cards to form the deck. In a two player game 9 cards are removed at random so there will be only 5 goods deliveries not 6 as normal. ==End of the round== The round ends and is scored when the last card is taken from the marketplace. Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand. You cannot play character cards; you cannot add to existing sets. All cards remaining in the players hand are added to their corruption pile. Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs. Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols. == Game end == The game ends after 3 rounds. The game can end early if one player gets more than 100 points. 2dd90054a4b137a1b6f7c5110f419db39da80fef Gamehelpintheyearofthedragon 0 51 1412 558 2015-03-31T13:10:52Z Squarerootofthree 5668 /* End-of-round Scoring */ wikitext text/x-wiki === Round Order === The game consists of exactly 12 rounds, symbolizing the 12 months in the Year of the Dragon. Each round consists of the following 4 phases, in order: * 1st Phase: Choose an Action ** If you choose an action in the same grouping as another player has already chosen, you must pay 3 yuan. * 2nd Phase: Choose a New Person ** If you do not have available space in any palaces, you must discard a different person before placing your new person. * 3rd Phase: Event ** After the event resolves, any palaces which are unoccupied lose 1 floor. * 4th Phase: Scoring === End-of-round Scoring === * 1 point for each palace. * 1 point For each court lady. * 1 point For each privilege. (Small privilege = 1 point; Large privilege = 2 points) === End-of-game Scoring === * 2 points for each person tile. * For each monk: score [number of Buddhas] x [number of floors] points. * Each player sells back to the supply all of his rice and fireworks tiles for 2 yuan each.Afterward, each player earns 1 victory point for every 3 yuan he possesses. c56efba0650e6314d4afa8961723bdfa1120be55 1413 1412 2015-03-31T13:11:05Z Squarerootofthree 5668 /* End-of-game Scoring */ wikitext text/x-wiki === Round Order === The game consists of exactly 12 rounds, symbolizing the 12 months in the Year of the Dragon. Each round consists of the following 4 phases, in order: * 1st Phase: Choose an Action ** If you choose an action in the same grouping as another player has already chosen, you must pay 3 yuan. * 2nd Phase: Choose a New Person ** If you do not have available space in any palaces, you must discard a different person before placing your new person. * 3rd Phase: Event ** After the event resolves, any palaces which are unoccupied lose 1 floor. * 4th Phase: Scoring === End-of-round Scoring === * 1 point for each palace. * 1 point For each court lady. * 1 point For each privilege. (Small privilege = 1 point; Large privilege = 2 points) === End-of-game Scoring === * 2 points for each person tile. * For each monk: score [number of Buddhas] x [number of floors] points. * Each player sells back to the supply all of his rice and fireworks tiles for 2 yuan each. Afterward, each player earns 1 victory point for every 3 yuan he possesses. 4c1b6aa085909bd9e18aa88869bb0ded1736807f Game art: img directory 0 89 1417 986 2015-04-04T04:13:05Z Wucnuc 8500 /* Requested images */ wikitext text/x-wiki == Requested images == The following images are requested by BGA: ;game_box.png * It is displayed on the main site on the game description page and when creating a table (280x280 px). * It should be a 3D image of a physical copy of the game box as it appears in an online shop. * It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game. * The background of the image must be transparent. * If you don't have a 3D version of the game box, you can use the following website to create one: http://www.3d-pack.com/ ;game_icon.png * It is the icon displayed in the lists of games and tables (50x50 px). * This one should not be transparent, and shouldn't have a border (a black border will be add by BGA). * The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title). ;publisher.png * It is the logo of the publisher of the game, displayed on the game description page. * The width must be 150 px. The height can be anything. The image could be transparent. ;publisher2.png (optional) * If the game has been co-published by 2 publishers, you should upload a second image named "publisher2.png" (same characteristics as the first one). '''Important''': when you modify these images, you MUST click on "Reload game box image" from the Control Panel in order your update can be taken into account. == Game art == You must upload in img directory all images of your game interface. === Images loading === '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. Note that you can tune the way images are loaded with Javascript method "dontPreloadImage" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]). === Images format === You can use 3 image format while building your game interface: ;jpg images should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load. ;png images should be used for transparent images. ;gif images can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful. === Use CSS Sprites === To limit the number of images load and make the game load faster, you must use CSS sprites, ie you must gather several images in a single one. To learn more on CSS Sprites: * [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites (W3C documentation)]. * [[Game interface stylesheet: yourgamename.css]] c421d2ef61a20faa2fecdb8c5752b16b0445cf31 Gamehelpassyria 0 190 1418 2015-04-05T00:24:15Z Zanthian 1851 Created page with " == Summary of the game == '''GAME TURN'''<br> I - Farming:<br> : A) Sowing: the first player draws 5 Food cards twice and places them in order<br> : B) Harvest: in turn or..." wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> I - Farming:<br> : A) Sowing: the first player draws 5 Food cards twice and places them in order<br> : B) Harvest: in turn order, each player chooses one of the 2-card columns<br> : C) New turn order: depending on the columns that are chosen, a new turn order arises<br> II - Expansion: each player, in turn order, performs all of the actions below.<br> : A) New huts: the player places a number of huts corresponding to the value of the Expansion of the current turn<br> : B) Resupplying: using their cards, the player resupplies their huts<br> : C) Famine: unsupplied huts are removed from the board<br> : D) Wells: the player may place wells on the intersection of 3 hexagons on which they have huts<br> : E) Revenue & prestige: the player earns camels and scores points<br> III - Actions: each player, in turn order, spends their camels (totally or in part)<br> : A) Build / extend a ziggurat<br> : B) Create intrigue in Assur<br> : C) Make an offering to the gods<br> : D) Buy a Plow or Food card<br> End of turn: If this is not the end of a Reign, place a new Expansion card. Otherwise, a Flood takes place.<br> '''FLOOD'''<br> :I) Flooding: each hut located on the river is removed<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> At the end of the 3rd Reign, players score 1 point per ziggurat tile, 1 point per Plow card and 1 point for each group of 2 remaining camels. 00f2441a07cbf72fba679674b08ab8339f768222 1419 1418 2015-04-05T08:41:59Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます<br> II - Expansion: each player, in turn order, performs all of the actions below.<br> : A) New huts: the player places a number of huts corresponding to the value of the Expansion of the current turn<br> : B) Resupplying: using their cards, the player resupplies their huts<br> : C) Famine: unsupplied huts are removed from the board<br> : D) Wells: the player may place wells on the intersection of 3 hexagons on which they have huts<br> : E) Revenue & prestige: the player earns camels and scores points<br> III - Actions: each player, in turn order, spends their camels (totally or in part)<br> : A) Build / extend a ziggurat<br> : B) Create intrigue in Assur<br> : C) Make an offering to the gods<br> : D) Buy a Plow or Food card<br> End of turn: If this is not the end of a Reign, place a new Expansion card. Otherwise, a Flood takes place.<br> '''FLOOD'''<br> :I) Flooding: each hut located on the river is removed<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> At the end of the 3rd Reign, players score 1 point per ziggurat tile, 1 point per Plow card and 1 point for each group of 2 remaining camels. 61f475f6184815314d3b99a0db815cd2a1fe8c18 1420 1419 2015-04-05T08:48:30Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します.<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。(自分のジッグラトもしくは小屋に隣接しているところに)<br> : B) Resupplying: using their cards, the player resupplies their huts<br> : C) Famine: unsupplied huts are removed from the board<br> : D) Wells: the player may place wells on the intersection of 3 hexagons on which they have huts<br> : E) Revenue & prestige: the player earns camels and scores points<br> III - Actions: each player, in turn order, spends their camels (totally or in part)<br> : A) Build / extend a ziggurat<br> : B) Create intrigue in Assur<br> : C) Make an offering to the gods<br> : D) Buy a Plow or Food card<br> End of turn: If this is not the end of a Reign, place a new Expansion card. Otherwise, a Flood takes place.<br> '''FLOOD'''<br> :I) Flooding: each hut located on the river is removed<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> At the end of the 3rd Reign, players score 1 point per ziggurat tile, 1 point per Plow card and 1 point for each group of 2 remaining camels. 4ac9a7eac1571ac64d26beb0d6926a546c8946dd 1421 1420 2015-04-05T08:59:50Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。(自分のジッグラトもしくは小屋に隣接しているところに)<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br> ラクダ<br> <br> <br> III - Actions: each player, in turn order, spends their camels (totally or in part)<br> : A) Build / extend a ziggurat<br> : B) Create intrigue in Assur<br> : C) Make an offering to the gods<br> : D) Buy a Plow or Food card<br> End of turn: If this is not the end of a Reign, place a new Expansion card. Otherwise, a Flood takes place.<br> '''FLOOD'''<br> :I) Flooding: each hut located on the river is removed<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> At the end of the 3rd Reign, players score 1 point per ziggurat tile, 1 point per Plow card and 1 point for each group of 2 remaining camels. 6ba2410e88a04598253ebbb39bfe95ee8abe375f 1422 1421 2015-04-05T09:11:25Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。(自分のジッグラトもしくは小屋に隣接しているところに)<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br> ラクダの獲得:川の上の小屋につき、最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン<br> 小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント。 新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - Actions: each player, in turn order, spends their camels (totally or in part)<br> : A) Build / extend a ziggurat<br> : B) Create intrigue in Assur<br> : C) Make an offering to the gods<br> : D) Buy a Plow or Food card<br> End of turn: If this is not the end of a Reign, place a new Expansion card. Otherwise, a Flood takes place.<br> '''FLOOD'''<br> :I) Flooding: each hut located on the river is removed<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> At the end of the 3rd Reign, players score 1 point per ziggurat tile, 1 point per Plow card and 1 point for each group of 2 remaining camels. 7aec820f879867f70b2c8857aab906adb06bc104 1423 1422 2015-04-05T09:26:18Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。(自分のジッグラトもしくは小屋に隣接しているところに)<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - アクション:Ⅱで獲得したラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上に建設は出来ない)⇒コスト:6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) Create intrigue in Assur<br> : C) Make an offering to the gods<br> : D) Buy a Plow or Food card<br> End of turn: If this is not the end of a Reign, place a new Expansion card. Otherwise, a Flood takes place.<br> '''FLOOD'''<br> :I) Flooding: each hut located on the river is removed<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> At the end of the 3rd Reign, players score 1 point per ziggurat tile, 1 point per Plow card and 1 point for each group of 2 remaining camels. 85d7050aab7d4ee27dec9b12faa35b297e036f30 1424 1423 2015-04-05T09:30:39Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。(自分のジッグラトもしくは小屋に隣接しているところに)<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - アクション:Ⅱで獲得したラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上に建設は出来ない)⇒コスト:6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) Create intrigue in Assur<br> : C) Make an offering to the gods<br> : D) Buy a Plow or Food card<br> End of turn: If this is not the end of a Reign, place a new Expansion card. Otherwise, a Flood takes place.<br> '''FLOOD'''<br> :I) Flooding: each hut located on the river is removed<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> ジッグラトレベルにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。 548dc2b546dedf0fa4ac5241818ec30e7135493f 1425 1424 2015-04-05T09:31:36Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。(自分のジッグラトもしくは小屋に隣接しているところに)<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - アクション:Ⅱで獲得したラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上に建設は出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) Create intrigue in Assur<br> : C) Make an offering to the gods<br> : D) Buy a Plow or Food card<br> End of turn: If this is not the end of a Reign, place a new Expansion card. Otherwise, a Flood takes place.<br> '''FLOOD'''<br> :I) Flooding: each hut located on the river is removed<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> ジッグラトレベルにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。 9e713ffee9bbd56e962b1e83dcb64bb8278e84e4 1426 1425 2015-04-05T09:32:10Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。(自分のジッグラトもしくは小屋に隣接しているところに)<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上に建設は出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) Create intrigue in Assur<br> : C) Make an offering to the gods<br> : D) Buy a Plow or Food card<br> End of turn: If this is not the end of a Reign, place a new Expansion card. Otherwise, a Flood takes place.<br> '''FLOOD'''<br> :I) Flooding: each hut located on the river is removed<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> ジッグラトレベルにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。 ab3423aed3ea0c5ac117fc361b4ee147dfdb431f 1427 1426 2015-04-05T09:35:52Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。(自分のジッグラトもしくは小屋に隣接しているところに)<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上に建設は出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) Create intrigue in Assur<br> : C) Make an offering to the gods<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダトークン。食糧カード:収穫ターンで残ったカードに対応したラクダトークン。<br> End of turn: If this is not the end of a Reign, place a new Expansion card. Otherwise, a Flood takes place.<br> '''FLOOD'''<br> :I) Flooding: each hut located on the river is removed<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> ジッグラトレベルにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。 21b6c4c26e29be440ddb77c646a26dd4d795d8e0 1428 1427 2015-04-05T09:38:00Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。(自分のジッグラトもしくは小屋に隣接しているところに)<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上に建設は出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) アッシュールでの陰謀:<br> : C) 神様への貢ぎ物:<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダトークン。食糧カード:収穫ターンで残ったカードに対応したラクダトークン。<br> End of turn: If this is not the end of a Reign, place a new Expansion card. Otherwise, a Flood takes place.<br> '''FLOOD'''<br> :I) Flooding: each hut located on the river is removed<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> ジッグラトレベルにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。 2363fde7ca0eef603a42e31accae570b9415577c 1429 1428 2015-04-05T09:41:40Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。(自分のジッグラトもしくは小屋に隣接しているところに)<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上に建設は出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) アッシュールでの陰謀:<br> : C) 神様への貢ぎ物:<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダトークン。食糧カード:収穫ターンで残ったカードに対応したラクダトークン。<br> End of turn: If this is not the end of a Reign, place a new Expansion card. Otherwise, a Flood takes place.<br> '''FLOOD'''<br> :I) Flooding: each hut located on the river is removed<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> ジッグラトレベルにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。 949cdcd80716deee5a156620ea40bde040bef006 1430 1429 2015-04-05T09:44:29Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。(自分のジッグラトもしくは小屋に隣接しているところに)<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上に建設は出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) アッシュールでの陰謀:<br> : C) 神様への貢ぎ物:<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダトークン。食糧カード:収穫ターンで残ったカードに対応したラクダトークン。<br> <br> ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合洪水が起こります。.<br> '''FLOOD'''<br> :I) Flooding: each hut located on the river is removed<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> ジッグラトレベルにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。 234147c340bd0bda657d43ba94205ce7caa65eed 1431 1430 2015-04-05T09:47:51Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。(自分のジッグラトもしくは小屋に隣接しているところに)<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上に建設は出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) アッシュールでの陰謀:<br> : C) 神様への貢ぎ物:<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダトークン。食糧カード:収穫ターンで残ったカードに対応したラクダトークン。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。.<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> ジッグラトレベルにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。 550c33fbb7fa0112ad7c3e3b3917571dc7bb8b4c 1432 1431 2015-04-05T09:51:04Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。(自分のジッグラトもしくは小屋に隣接しているところに)<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上に建設は出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) アッシュールでの陰謀:<br> : C) 神様への貢ぎ物:<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダトークン。食糧カード:収穫ターンで残ったカードに対応したラクダトークン。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> ジッグラトレベルにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。 0dd2b792b4637f980d2d287d13db1cd8951f3eaf 1433 1432 2015-04-05T11:50:05Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。(自分のジッグラトもしくは小屋に隣接しているところに)<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上に建設は出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) アッシュールでの陰謀:<br> : C) 神様への貢ぎ物:<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダトークン。食糧カード:収穫ターンで残ったカードに対応したラクダトークン。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> ジッグラトレベルにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。 7e49f30a586b2bb06c31a2becb48605cf2e58e19 1434 1433 2015-04-05T14:40:04Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。(自分のジッグラトもしくは小屋に隣接しているところに)<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸の設置ヘクスには建設出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) アッシュールでの陰謀:<br> : C) 神様への貢ぎ物:<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダトークン。食糧カード:収穫ターンで残ったカードに対応したラクダトークン。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> ジッグラトレベルにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。 6cc6a9deee8f8a1771a3eaa610c45c878ea2c8e3 1435 1434 2015-04-05T17:47:36Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダトークン、各川に1つずつならば6ラクダトークン)<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸の設置ヘクスには建設出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) アッシュールでの陰謀:<br> : C) 神様への貢ぎ物:<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダトークン。食糧カード:収穫ターンで残ったカードに対応したラクダトークン。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> ジッグラトレベルにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。 171c5ace64da5cd249d30f31fc49ffbe585e64f4 1436 1435 2015-04-05T18:07:54Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤(すき)は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダトークン、各川に1つずつならば6ラクダトークン)<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸の設置ヘクスには建設出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) アッシュールでの陰謀:<br> : C) 神様への貢ぎ物:<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダトークン。食糧カード:収穫ターンで残ったカードに対応したラクダトークン。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> ジッグラトレベルにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。 8d97bf1f8373a0b753b93baa42fcbc290eff53c3 1437 1436 2015-04-05T18:36:35Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダトークン、各川に1つずつならば6ラクダトークン)<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸の設置ヘクスには建設出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) アッシュールでの陰謀:<br> : C) 神様への貢ぎ物:<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダトークン。食糧カード:収穫ターンで残ったカードに対応したラクダトークン。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) アッシュール:アッシュールの陰謀で神官に置いた駒によりポイントを得ます。高位1つにつき3ポイント。中位1つにつき2ポイント。低位1つにつき1ポイント。<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> ジッグラトレベルにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。 e6569dcbb475958a257d58926708be09ba6644ae 1438 1437 2015-04-05T18:50:46Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダトークン、各川に1つずつならば6ラクダトークン)<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトレベルにつき1ポイント()<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラトは自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸に隣接するヘクスには建設出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。<br> : B) アッシュールでの陰謀:<br> : C) 神様への供物:<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダトークン。食糧カード:収穫ターンで残ったカードに対応したラクダトークン。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) アッシュール:アッシュールの陰謀で神官に置いた駒によりポイントを得ます。高位1つにつき3ポイント。中位1つにつき2ポイント。低位1つにつき1ポイント。<br> :III) 神官ボーナス:アッシュールの陰謀で各神官に置いたボーナスを受け取ります。<br> :IV)供物報酬:(供物トラックの倍率×ジッグラトの数)のポイントを得ます。ジッグラトのレベルではなく(土台部分の)数です。<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> ジッグラトレベルにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。 d2c0aa054d182f87ecf0958a803d2e361047a2cb 1439 1438 2015-04-05T19:05:08Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダトークン、各川に1つずつならば6ラクダトークン)<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラト(土台部分)は自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸に隣接するヘクスには建設出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。土台部分→中央部分→屋根部分と順に積み上げて建築します。<br> : B) アッシュールでの陰謀:<br> : C) 神様への供物:<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダトークン。食糧カード:収穫ターンで残ったカードに対応したラクダトークン。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) アッシュール:アッシュールの陰謀で神官に置いた駒によりポイントを得ます。高位1つにつき3ポイント。中位1つにつき2ポイント。低位1つにつき1ポイント。<br> :III) 神官ボーナス:アッシュールの陰謀で各神官に置いたボーナスを受け取ります。<br> :IV)供物報酬:(供物トラックの倍率×ジッグラトの土台部分の数)のポイントを得ます。<br> :V) 次の治世へ:供物トラックを0に戻し、神官に置いた駒もすべて取り除き次の治世へ移ります。<br> '''ゲーム終了'''<br> 第3治世終了後以下のボーナスを加えて得点計算。最も点数が高かったプレイヤーの勝利。<br> ジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。<br> 7864ab9a453dc522d2a8ac9abfa06708334b337d 1440 1439 2015-04-05T19:21:01Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダトークン・2戸目以降は1戸につき2ラクダトークン(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダトークン、各川に1つずつならば6ラクダトークン)<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを行います<br> : A) ジッグラトの拡張・構築:新たなジッグラト(土台部分)は自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸に隣接するヘクスには建設出来ない)。:コスト6ラクダトークン。中央部分の拡張:コスト3ラクダトークン。屋根部分の拡張:コスト2ラクダトークン。土台部分→中央部分→屋根部分と順に積み上げて建築します。<br> : B) アッシュールでの陰謀:高位神官に1つ駒を置く:コスト4ラクダトークン。中位神官に1つ駒を置く:コスト3ラクダトークン。低位神官に1つ駒を置く:コスト2ラクダトークン。<br> : C) 神様への供物:コストを支払い供物トラックを進めます。<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダトークン。食糧カード:収穫ターンで残ったカードに対応したラクダトークン。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) アッシュール:アッシュールの陰謀で神官に置いた駒によりポイントを得ます。高位1つにつき3ポイント。中位1つにつき2ポイント。低位1つにつき1ポイント。<br> :III) 神官ボーナス:アッシュールの陰謀で各神官に置いたボーナスを受け取ります。高位:小屋1戸で1ポイント・2戸で4ポイント・3戸で8ポイント。中位:鋤カード1枚。低位:小屋1戸で1ラクダトークン。<br> :IV)供物報酬:(供物トラックの倍率×ジッグラトの土台部分の数)のポイントを得ます。<br> :V) 次の治世へ:供物トラックを0に戻し、神官に置いた駒もすべて取り除き次の治世へ移ります。<br> '''ゲーム終了'''<br> 第3治世終了後以下のボーナスを加えて得点計算。最も点数が高かったプレイヤーの勝利。<br> ジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。<br> 31e315236d5f560a543f8dc2f7a27b635b598711 1441 1440 2015-04-06T09:07:30Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、ポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダ・2戸目以降は1戸につき2ラクダ(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダ、各川に1つずつならば6ラクダ)。獲得したラクダ分だけラクダトラックを進めます。<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1戸につき6ポイント・第2治世1戸につき5ポイント・第3治世1戸につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを可能なかぎり行うことができます。全てのラクダを使いきらなくてもかまいません。<br> : A) ジッグラトの拡張・構築:新たなジッグラト(土台部分)は自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸に隣接するヘクスには建設出来ない)。:コスト6ラクダ。中央部分の拡張:コスト3ラクダ。屋根部分の拡張:コスト2ラクダ。土台部分→中央部分→屋根部分と順に積み上げて建築します。<br> : B) アッシュールでの陰謀:高位神官に1つ駒を置く:コスト4ラクダ。中位神官に1つ駒を置く:コスト3ラクダ。低位神官に1つ駒を置く:コスト2ラクダ。<br> : C) 神様への供物:コストを支払い供物トラックを進めます。<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダ。食糧カード:収穫ターンで残ったカードに対応したラクダ。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) アッシュール:アッシュールの陰謀で神官に置いた駒によりポイントを得ます。高位1つにつき3ポイント。中位1つにつき2ポイント。低位1つにつき1ポイント。<br> :III) 神官ボーナス:アッシュールの陰謀で各神官に置いたボーナスを受け取ります。高位:小屋1戸で1ポイント・2戸で4ポイント・3戸で8ポイント。中位:鋤カード1枚。低位:小屋1戸で1ラクダ。<br> :IV)供物報酬:(供物トラックの倍率×ジッグラトの土台部分の数)のポイントを得ます。<br> :V) 次の治世へ:供物トラックを0に戻し、神官に置いた駒もすべて取り除き次の治世へ移ります。<br> '''ゲーム終了'''<br> 第3治世終了後以下のボーナスを加えて得点計算。最も点数が高かったプレイヤーの勝利。<br> ジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。<br> dfa8e066658b366d2e2a0ac0d64a5c69bb445880 1442 1441 2015-04-06T09:09:41Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、以下のポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダ・2戸目以降は1戸につき2ラクダ(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダ、各川に1つずつならば6ラクダ)。獲得したラクダ分だけラクダトラックを進めます。<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1基につき6ポイント・第2治世1基につき5ポイント・第3治世1基につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを可能なかぎり行うことができます。全てのラクダを使いきらなくてもかまいません。<br> : A) ジッグラトの拡張・構築:新たなジッグラト(土台部分)は自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸に隣接するヘクスには建設出来ない)。:コスト6ラクダ。中央部分の拡張:コスト3ラクダ。屋根部分の拡張:コスト2ラクダ。土台部分→中央部分→屋根部分と順に積み上げて建築します。<br> : B) アッシュールでの陰謀:高位神官に1つ駒を置く:コスト4ラクダ。中位神官に1つ駒を置く:コスト3ラクダ。低位神官に1つ駒を置く:コスト2ラクダ。<br> : C) 神様への供物:コストを支払い供物トラックを進めます。<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダ。食糧カード:収穫ターンで残ったカードに対応したラクダ。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) アッシュール:アッシュールの陰謀で神官に置いた駒によりポイントを得ます。高位1つにつき3ポイント。中位1つにつき2ポイント。低位1つにつき1ポイント。<br> :III) 神官ボーナス:アッシュールの陰謀で各神官に置いたボーナスを受け取ります。高位:小屋1戸で1ポイント・2戸で4ポイント・3戸で8ポイント。中位:鋤カード1枚。低位:小屋1戸で1ラクダ。<br> :IV)供物報酬:(供物トラックの倍率×ジッグラトの土台部分の数)のポイントを得ます。<br> :V) 次の治世へ:供物トラックを0に戻し、神官に置いた駒もすべて取り除き次の治世へ移ります。<br> '''ゲーム終了'''<br> 第3治世終了後以下のボーナスを加えて得点計算。最も点数が高かったプレイヤーの勝利。<br> ジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。<br> 164f277a8aeeec98db5a8da1289344e003ab2335 1443 1442 2015-04-06T09:29:05Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。ここで1ラクダのカードを選んだら、次の農業ターンの順番がより前に、2ラクダのカードを選んだらより後になります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、以下のポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダ・2戸目以降は1戸につき2ラクダ(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダ、各川に1つずつならば6ラクダ)。獲得したラクダ分だけラクダトラックを進めます。<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1基につき6ポイント・第2治世1基につき5ポイント・第3治世1基につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを可能なかぎり行うことができます。全てのラクダを使いきらなくてもかまいません。<br> : A) ジッグラトの拡張・構築:新たなジッグラト(土台部分)は自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸に隣接するヘクスには建設出来ない)。:コスト6ラクダ。中央部分の拡張:コスト3ラクダ。屋根部分の拡張:コスト2ラクダ。土台部分→中央部分→屋根部分と順に積み上げて建築します。<br> : B) アッシュールでの陰謀:高位神官に1つ駒を置く:コスト4ラクダ。中位神官に1つ駒を置く:コスト3ラクダ。低位神官に1つ駒を置く:コスト2ラクダ。<br> : C) 神様への供物:コストを支払い供物トラックを進めます。<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダ。食糧カード:収穫ターンで残ったカードに対応したラクダ。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) アッシュール:アッシュールの陰謀で神官に置いた駒によりポイントを得ます。高位1つにつき3ポイント。中位1つにつき2ポイント。低位1つにつき1ポイント。<br> :III) 神官ボーナス:アッシュールの陰謀で各神官に置いたボーナスを受け取ります。高位:小屋1戸で1ポイント・2戸で4ポイント・3戸で8ポイント。中位:鋤カード1枚。低位:小屋1戸で1ラクダ。<br> :IV)供物報酬:(供物トラックの倍率×ジッグラトの土台部分の数)のポイントを得ます。<br> :V) 次の治世へ:供物トラックを0に戻し、神官に置いた駒もすべて取り除き次の治世へ移ります。<br> '''ゲーム終了'''<br> 第3治世終了後以下のボーナスを加えて得点計算。最も点数が高かったプレイヤーの勝利。<br> ジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残ったラクダトークン2枚につき1ポイント。<br> 04f6b76b009311069e3491b9e138d9aee250ff02 1444 1443 2015-04-06T11:10:55Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。ここで1ラクダのカードを選んだら、次の農業ターンの順番がより前に、2ラクダのカードを選んだらより後になります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、以下のポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダ・2戸目以降は1戸につき2ラクダ(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダ、各川に1つずつならば6ラクダ)。獲得したラクダ分だけラクダトラックを進めます。<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1基につき6ポイント・第2治世1基につき5ポイント・第3治世1基につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを可能なかぎり行うことができます。全てのラクダを使いきらなくてもかまいません。<br> : A) ジッグラトの拡張・構築:新たなジッグラト(土台部分)は自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸に隣接するヘクスには建設出来ない)。:コスト6ラクダ。中央部分の拡張:コスト3ラクダ。屋根部分の拡張:コスト2ラクダ。土台部分→中央部分→屋根部分と順に積み上げて建築します。<br> : B) アッシュールでの陰謀:高位神官に1つ駒を置く:コスト4ラクダ。中位神官に1つ駒を置く:コスト3ラクダ。低位神官に1つ駒を置く:コスト2ラクダ。<br> : C) 神様への供物:コストを支払い供物トラックを進めます。<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダ。食糧カード:収穫ターンで残ったカードに対応したラクダ。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) アッシュール:アッシュールの陰謀で神官に置いた駒によりポイントを得ます。高位1つにつき3ポイント。中位1つにつき2ポイント。低位1つにつき1ポイント。<br> :III) 神官ボーナス:アッシュールの陰謀で各神官に置いたボーナスを受け取ります。高位:小屋1戸で1ポイント・2戸で4ポイント・3戸で8ポイント。中位:鋤カード1枚。低位:小屋1戸で1ラクダ。<br> :IV)供物報酬:(供物トラックの倍率×ジッグラトの土台部分の数)のポイントを得ます。<br> :V) 次の治世へ:供物トラックを0に戻し、神官に置いた駒もすべて取り除き次の治世へ移ります。<br> '''ゲーム終了'''<br> 第3治世終了後以下のボーナスを加えて得点計算。最も点数が高かったプレイヤーの勝利。<br> ジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残った2ラクダにつき1ポイント。<br> 66f58bc40c8a1ae7c9e4aa874cdd785f6199f49e 1445 1444 2015-04-06T12:43:11Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。ここで1ラクダのカードを選んだら、次の農業ターンの順番がより前に、2ラクダのカードを選んだらより後になります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、以下のポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダ・2戸目以降は1戸につき2ラクダ(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダ、各川に1つずつならば6ラクダ)。獲得したラクダ分だけラクダトラックを進めます。<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1基につき6ポイント・第2治世1基につき5ポイント・第3治世1基につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを可能なかぎり行うことができます。全てのラクダを使いきらなくてもかまいません。<br> : A) ジッグラトの拡張・構築:新たなジッグラト(土台部分)は自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸に隣接するヘクスには建設出来ない)。:コスト6ラクダ。中央部分の拡張:コスト3ラクダ。屋根部分の拡張:コスト2ラクダ。土台部分→中央部分→屋根部分と順に積み上げて建築します。<br> : B) アッシュールでの陰謀:高位神官に1戸小屋を置く:コスト4ラクダ(プレイヤー全体最大で3)。中位神官に1戸小屋を置く:コスト3ラクダ(プレイヤー全体最大で4)。低位神官に1戸小屋を置く:コスト2ラクダ(プレイヤー全体最大で6)。<br> : C) 神様への供物:コストを支払い供物トラックを進めます。<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダ。食糧カード:収穫ターンで残ったカードに対応したラクダ。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) アッシュールの影響:アッシュールの陰謀で神官に置いた小屋によりポイントを得ます。高位1つにつき3ポイント。中位1つにつき2ポイント。低位1つにつき1ポイント。<br> :III) 神官ボーナス:アッシュールの陰謀で各神官に置いたボーナスを受け取ります。高位:置いた小屋1戸で1ポイント・2戸で4ポイント・3戸で8ポイント。中位:鋤カード1枚。低位:小屋1戸で1ラクダ。<br> :IV)供物報酬:(供物トラックの倍率×ジッグラトの土台部分の数)のポイントを得ます。<br> :V) 次の治世へ:供物トラックを0に戻し、神官に置いた駒もすべて取り除き次の治世へ移ります。<br> '''ゲーム終了'''<br> 第3治世終了後以下のボーナスを加えて得点計算。最も点数が高かったプレイヤーの勝利。<br> ジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残った2ラクダにつき1ポイント。<br> ffba5c8d9ac163cddadcdd6d21c6f7818f432188 1446 1445 2015-04-06T12:44:19Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。ここで1ラクダのカードを選んだら、次の農業ターンの順番がより前に、2ラクダのカードを選んだらより後になります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、以下のポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダ・2戸目以降は1戸につき2ラクダ(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダ、各川に1つずつならば6ラクダ)。獲得したラクダ分だけラクダトラックを進めます。<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1基につき6ポイント・第2治世1基につき5ポイント・第3治世1基につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを可能なかぎり行うことができます。全てのラクダを使いきらなくてもかまいません。<br> : A) ジッグラトの拡張・構築:新たなジッグラト(土台部分)は自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸に隣接するヘクスには建設出来ない)。:コスト6ラクダ。中央部分の拡張:コスト3ラクダ。屋根部分の拡張:コスト2ラクダ。土台部分→中央部分→屋根部分と順に積み上げて建築します。<br> : B) アッシュールでの陰謀:高位神官に1戸小屋を置く:コスト4ラクダ(プレイヤー全体最大で3)。中位神官に1戸小屋を置く:コスト3ラクダ(プレイヤー全体最大で4)。低位神官に1戸小屋を置く:コスト2ラクダ(プレイヤー全体最大で6)。<br> : C) 神様への供物:コストを支払い供物トラックを進めます。<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダ。食糧カード:収穫ターンで残ったカードに対応したラクダ。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) アッシュールの影響:アッシュールの陰謀で神官に置いた小屋によりポイントを得ます。高位1つにつき3ポイント。中位1つにつき2ポイント。低位1つにつき1ポイント。<br> :III) 神官ボーナス:アッシュールの陰謀で各神官に置いたボーナスを受け取ります。高位:置いた小屋1戸で1ポイント・2戸で4ポイント・3戸で8ポイント。中位:鋤カード1枚。低位:置いた小屋1戸で1ラクダ。<br> :IV)供物報酬:(供物トラックの倍率×ジッグラトの土台部分の数)のポイントを得ます。<br> :V) 次の治世へ:供物トラックを0に戻し、神官に置いた駒もすべて取り除き次の治世へ移ります。<br> '''ゲーム終了'''<br> 第3治世終了後以下のボーナスを加えて得点計算。最も点数が高かったプレイヤーの勝利。<br> ジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残った2ラクダにつき1ポイント。<br> 4ebc1fc4415490563b522f399be3bf2f5f1be0e5 1447 1446 2015-04-06T13:58:24Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。ここで1ラクダのカードを選んだら、次の農業ターンの順番がより前に、2ラクダのカードを選んだらより後になります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大の値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、以下のポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダ・2戸目以降は1戸につき2ラクダ(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダ、各川に1つずつならば6ラクダ)。獲得したラクダ分だけラクダトラックを進めます。<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1基につき6ポイント・第2治世1基につき5ポイント・第3治世1基につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを可能なかぎり行うことができます。全てのラクダを使いきらなくてもかまいません。<br> : A) ジッグラトの拡張・構築:新たなジッグラト(土台部分)は自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸に隣接するヘクスには建設出来ない)。:コスト6ラクダ。中央部分の拡張:コスト3ラクダ。屋根部分の拡張:コスト2ラクダ。土台部分→中央部分→屋根部分と順に積み上げて建築します。<br> : B) アッシュールでの陰謀:高位神官に1戸小屋を置く:コスト4ラクダ(プレイヤー全体最大で3)。中位神官に1戸小屋を置く:コスト3ラクダ(プレイヤー全体最大で4)。低位神官に1戸小屋を置く:コスト2ラクダ(プレイヤー全体最大で6)。<br> : C) 神様への供物:コストを支払い供物トラックを進めます。<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダ。食糧カード:収穫ターンで残ったカードに対応したラクダ。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) アッシュールの影響:アッシュールの陰謀で神官に置いた小屋の影響力によりポイントを得ます。<br> :III) 神官ボーナス:アッシュールの陰謀で各神官に置いたボーナスを受け取ります。高位:置いた小屋1戸で1ポイント・2戸で4ポイント・3戸で8ポイント。中位:鋤カード1枚。低位:置いた小屋1戸で1ラクダ。<br> :IV)供物報酬:(供物トラックの倍率×ジッグラトの土台部分の数)のポイントを得ます。<br> :V) 次の治世へ:供物トラックを0に戻し、神官に置いた駒もすべて取り除き次の治世へ移ります。<br> '''ゲーム終了'''<br> 第3治世終了後以下のボーナスを加えて得点計算。最も点数が高かったプレイヤーの勝利。<br> ジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残った2ラクダにつき1ポイント。<br> 6c437b11a6ad1ad3734b5ac830704bb1ff26fcff 1448 1447 2015-04-06T14:32:26Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。ここで1ラクダのカードを選んだら、次の農業ターンの順番がより前に、2ラクダのカードを選んだらより後になります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:拡大カードを1枚引いて場に置きます。各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大カードの値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、以下のポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダ・2戸目以降は1戸につき2ラクダ(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダ、各川に1つずつならば6ラクダ)。獲得したラクダ分だけラクダトラックを進めます。<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1基につき6ポイント・第2治世1基につき5ポイント・第3治世1基につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを可能なかぎり行うことができます。全てのラクダを使いきらなくてもかまいません。<br> : A) ジッグラトの拡張・構築:新たなジッグラト(土台部分)は自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸に隣接するヘクスには建設出来ない)。:コスト6ラクダ。中央部分の拡張:コスト3ラクダ。屋根部分の拡張:コスト2ラクダ。土台部分→中央部分→屋根部分と順に積み上げて建築します。<br> : B) アッシュールでの陰謀:高位神官に1戸小屋を置く:コスト4ラクダ(プレイヤー全体最大で3)。中位神官に1戸小屋を置く:コスト3ラクダ(プレイヤー全体最大で4)。低位神官に1戸小屋を置く:コスト2ラクダ(プレイヤー全体最大で6)。<br> : C) 神様への供物:コストを支払い供物トラックを進めます。<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダ。食糧カード:収穫ターンで残ったカードに対応したラクダ。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) アッシュールの影響:アッシュールの陰謀で神官に置いた小屋の合計影響力(高位:3・中位:2・低位:1)によりポイントを得ます。影響力1位のプレイヤーは拡大カード全部の合計ポイントを得ます。2位は最大の拡大カードを取り除いたポイントを得ます。3位は最大と2番目の拡大カードを取り除いたポイントを得ます(つまり第1治世は2位までになります)。同じ影響力の場合、より置いた小屋の数が多い方が上位になります。<br> :III) 神官ボーナス:アッシュールの陰謀で各神官に置いたボーナスを受け取ります。高位:置いた小屋1戸で1ポイント・2戸で4ポイント・3戸で8ポイント。中位:鋤カード1枚。低位:置いた小屋1戸で1ラクダ。<br> :IV)供物報酬:(供物トラックの倍率×ジッグラトの土台部分の数)のポイントを得ます。<br> :V) 次の治世へ:供物トラックを0に戻し、神官に置いた駒も、すべて取り除き次の治世へ移ります。<br> '''ゲーム終了'''<br> 第3治世終了後以下のボーナスを加えて得点計算。最も点数が高かったプレイヤーの勝利。<br> ジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残った2ラクダにつき1ポイント。<br> 35a5dba790433a7e3fb0ab79030b3e39b376d73b 1449 1448 2015-04-06T15:01:57Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:拡大カードを1枚引いて場に置きます。各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大カードの値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、以下のポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダ・2戸目以降は1戸につき2ラクダ(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダ、各川に1つずつならば6ラクダ)。獲得したラクダ分だけラクダトラックを進めます。<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1基につき6ポイント・第2治世1基につき5ポイント・第3治世1基につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを可能なかぎり行うことができます。全てのラクダを使いきらなくてもかまいません。<br> : A) ジッグラトの拡張・構築:新たなジッグラト(土台部分)は自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸に隣接するヘクスには建設出来ない)。:コスト6ラクダ。中央部分の拡張:コスト3ラクダ。屋根部分の拡張:コスト2ラクダ。土台部分→中央部分→屋根部分と順に積み上げて建築します。<br> : B) アッシュールでの陰謀:高位神官に1戸小屋を置く:コスト4ラクダ(プレイヤー全体最大で3)。中位神官に1戸小屋を置く:コスト3ラクダ(プレイヤー全体最大で4)。低位神官に1戸小屋を置く:コスト2ラクダ(プレイヤー全体最大で6)。<br> : C) 神様への供物:コストを支払い供物トラックを進めます。<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダ。食糧カード:収穫ターンで残ったカードに対応したラクダ。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) アッシュールの影響:アッシュールの陰謀で神官に置いた小屋の合計影響力(高位:3・中位:2・低位:1)によりポイントを得ます。影響力1位のプレイヤーは拡大カード全部の合計ポイントを得ます。2位は最大の拡大カードを取り除いたポイントを得ます。3位は最大と2番目の拡大カードを取り除いたポイントを得ます(つまり第1治世は2位までになります)。同じ影響力の場合、より置いた小屋の数が多い方が上位になります。<br> :III) 神官ボーナス:アッシュールの陰謀で各神官に置いたボーナスを受け取ります。高位:置いた小屋1戸で1ポイント・2戸で4ポイント・3戸で8ポイント。中位:鋤カード1枚。低位:置いた小屋1戸で1ラクダ。<br> :IV)供物報酬:(供物トラックの倍率×ジッグラトの土台部分の数)のポイントを得ます。<br> :V) 次の治世へ:供物トラックを0に戻し、神官に置いた駒も、すべて取り除き次の治世へ移ります。<br> '''ゲーム終了'''<br> 第3治世終了後以下のボーナスを加えて得点計算。最も点数が高かったプレイヤーの勝利。<br> ジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残った2ラクダにつき1ポイント。<br> 7f259549b2e457ce7a3ac880421b28f5f498e5c3 1450 1449 2015-04-06T15:03:47Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:拡大カードを1枚引いて場に置きます。各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大カードの値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、以下のポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダ・2戸目以降は1戸につき2ラクダ(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダ、各川に1つずつならば6ラクダ)。獲得したラクダ分だけラクダトラックを進めます。<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1基につき6ポイント・第2治世1基につき5ポイント・第3治世1基につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを可能なかぎり行うことができます。全てのラクダを使いきらなくてもかまいません。<br> : A) ジッグラトの拡張・構築:新たなジッグラト(土台部分)は自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸に隣接するヘクスには建設出来ない)。:コスト6ラクダ。中央部分の拡張:コスト3ラクダ。屋根部分の拡張:コスト2ラクダ。土台部分→中央部分→屋根部分と順に積み上げて建築します。<br> : B) アッシュールでの陰謀:高位神官に1戸小屋を置く:コスト4ラクダ(プレイヤー全体最大で3)。中位神官に1戸小屋を置く:コスト3ラクダ(プレイヤー全体最大で4)。低位神官に1戸小屋を置く:コスト2ラクダ(プレイヤー全体最大で6)。<br> : C) 神様への供物:コストを支払い供物トラックを進めます。<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダ。食糧カード:収穫ターンで残ったカードに対応したラクダ。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) アッシュールの影響:アッシュールの陰謀で神官に置いた小屋の合計影響力(高位:3・中位:2・低位:1)によりポイントを得ます。影響力1位のプレイヤーは拡大カード全部の合計ポイントを得ます。2位は最大の拡大カードを取り除いたポイントを得ます。3位は最大と2番目の拡大カードを取り除いたポイントを得ます(つまり第1治世は2位までになります)。同じ影響力の場合、より置いた小屋の数が多い方が上位になります。<br> :III) 神官ボーナス:アッシュールの陰謀で各神官に置いたボーナスを受け取ります。高位:置いた小屋1戸で1ポイント・2戸で4ポイント・3戸で8ポイント。中位:鋤カード1枚。低位:置いた小屋1戸で1ラクダ。<br> :IV)供物報酬:(供物トラックの倍率×ジッグラトの土台部分の数)のポイントを得ます。<br> :V) 次の治世へ:供物トラックを0に戻し、神官に置いた小屋も、出された拡大カードすべて取り除き次の治世へ移ります。<br> '''ゲーム終了'''<br> 第3治世終了後以下のボーナスを加えて得点計算。最も点数が高かったプレイヤーの勝利。<br> ジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残った2ラクダにつき1ポイント。<br> b7a59211167ee813a4f5105a8b117671fed1b77c 1451 1450 2015-04-06T15:08:10Z Sarasa1a 8234 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> <br> ゲームは全部で8ターン。第1・2ターンが第1治世、第3・4・5ターンが第2治世、第6・7・8ターンが第3治世。<br> ゲーム開始時に各プレイヤーは鋤(すき)カードを1枚受け取り、更に食糧カードを1枚ターン順に選び受け取ります。<br> <br> I - 農業:<br> : A) 種蒔き:ファーストプレイヤーはカードを5枚引きラクダ価値の高いものを右からに並べる(4人プレイの場合)。これを2列作る。<br> : B) 収穫:ターン順にいずれかの縦列の2枚のカードを貰う。<br> : C) 新しいターン順:収穫でより左側の列をとったプレイヤーから順に行動していきます。<br> II - 拡張:拡大カード(2・3・4いずれかの値が示されています)を1枚引いて場に置きます。各プレイヤーは、ターン順に、以下のすべてのアクションを実行します。<br> : A) 新しい小屋:プレイヤーは、現在のターンの拡大カードの値に対応する数だけ小屋を配置していきます。小屋が置けるのは自分のジッグラトもしくは小屋に隣接しているプレイヤーの小屋・ジッグラトが置かれていないヘクスです。<br> : B) 補給:自分のカードを使用して、小屋に対応した資源を補給していきます。鋤は任意の1つの種類すべてに補給できます。<br> : C) 飢饉:補給されなかった小屋をボードから取り除きます。<br> : D) 井戸:3つの小屋のヘクスが三角形を形成していた場合、その中心の交差点に井戸を設置します。井戸は川と川の間には設置できません。<br> : E) 収入と威信:小屋・井戸・ジッグラトから、以下のポイントとラクダを得ます。<br>    ●ラクダの獲得:川の上の小屋につき、各川最初の小屋は3ラクダ・2戸目以降は1戸につき2ラクダ(つまり同じ2つ川の上に置いた状態でも、1つの川に2つ置いていれば5ラクダ、各川に1つずつならば6ラクダ)。獲得したラクダ分だけラクダトラックを進めます。<br>    ●小屋とジッグラトによるポイントの獲得:川と川の間の小屋につき2ポイント・川の外側の小屋につき1ポイント。またジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。<br>    ●新しく建設した井戸によるポイントの獲得:第1治世1基につき6ポイント・第2治世1基につき5ポイント・第3治世1基につき4ポイント<br> <br> III - ラクダを使ってターン順にアクションを可能なかぎり行うことができます。全てのラクダを使いきらなくてもかまいません。<br> : A) ジッグラトの拡張・構築:新たなジッグラト(土台部分)は自分の小屋があるヘクス上に、小屋を取り除くことによって行います(川の上・井戸に隣接するヘクスには建設出来ない)。:コスト6ラクダ。中央部分の拡張:コスト3ラクダ。屋根部分の拡張:コスト2ラクダ。土台部分→中央部分→屋根部分と順に積み上げて建築します。<br> : B) アッシュールでの陰謀:高位神官に1戸小屋を置く:コスト4ラクダ(プレイヤー全体最大で3)。中位神官に1戸小屋を置く:コスト3ラクダ(プレイヤー全体最大で4)。低位神官に1戸小屋を置く:コスト2ラクダ(プレイヤー全体最大で6)。<br> : C) 神様への供物:コストを支払い供物トラックを進めます。<br> : D) 鋤カード・食糧カードの購入:鋤カード:コスト2ラクダ。食糧カード:収穫ターンで残ったカードに対応したラクダ。<br> <br>    ターン終了:新たな拡張カードを引き、さらに治世の終わりだった場合(第2・5・8ターン)洪水が起こります。<br> '''洪水'''<br> :I) 洪水:川の上にある小屋はすべて撤去されます。<br> :II) アッシュールの影響:アッシュールの陰謀で神官に置いた小屋の合計影響力(高位:3・中位:2・低位:1)によりポイントを得ます。影響力1位のプレイヤーは拡大カード全部の合計ポイントを得ます。2位は最大の拡大カードを取り除いたポイントを得ます。3位は最大と2番目の拡大カードを取り除いたポイントを得ます(つまり第1治世は2位までになります)。同じ影響力の場合、より置いた小屋の数が多い方が上位になります。<br> :III) 神官ボーナス:アッシュールの陰謀で各神官に置いたボーナスを受け取ります。高位:置いた小屋1戸で1ポイント・2戸で4ポイント・3戸で8ポイント。中位:鋤カード1枚。低位:置いた小屋1戸で1ラクダ。<br> :IV)供物報酬:(供物トラックの倍率×ジッグラトの土台部分の数)のポイントを得ます。<br> :V) 次の治世へ:供物トラックを0に戻し、神官に置いた小屋も、出された拡大カードすべて取り除き次の治世へ移ります。<br> '''ゲーム終了'''<br> 第3治世終了後以下のボーナスを加えて得点計算。最も点数が高かったプレイヤーの勝利。<br> ジッグラトの土台部分・中央部分・屋根部分それぞれにつき1ポイント。使わなかった食糧カード1枚につき1ポイント。残った2ラクダにつき1ポイント。<br> e1226cb7f2380661dc04f7a03441c9d3f7811700 Gamehelpassyria 0 190 1452 1451 2015-04-07T10:42:39Z Mikkabi 8544 wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> I - Farming:<br> : A) Sowing: the first player draws 5 Food cards twice and places them in order<br> : B) Harvest: in turn order, each player chooses one of the 2-card columns<br> : C) New turn order: depending on the columns that are chosen, a new turn order arises<br> II - Expansion: each player, in turn order, performs all of the actions below.<br> : A) New huts: the player places a number of huts corresponding to the value of the Expansion of the current turn<br> : B) Resupplying: using their cards, the player resupplies their huts<br> : C) Famine: unsupplied huts are removed from the board<br> : D) Wells: the player may place wells on the intersection of 3 hexagons on which they have huts<br> : E) Revenue & prestige: the player earns camels and scores points<br> III - Actions: each player, in turn order, spends their camels (totally or in part)<br> : A) Build / extend a ziggurat<br> : B) Create intrigue in Assur<br> : C) Make an offering to the gods<br> : D) Buy a Plow or Food card<br> End of turn: If this is not the end of a Reign, place a new Expansion card. Otherwise, a Flood takes place.<br> '''FLOOD'''<br> :I) Flooding: each hut located on the river is removed<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> At the end of the 3rd Reign, players score 1 point per ziggurat tile, 1 point per Plow card and 1 point for each group of 2 remaining camels. 00f2441a07cbf72fba679674b08ab8339f768222 Faq 0 3 1453 1357 2015-04-08T15:22:22Z Sourisdudesert 1 /* What can I do if I have an issue with the website? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. His turn will be skipped until he gets back, and if he doesn't get back he will get a "leave" penalty. In this case you have two options: ** Continue the game until the end. This is recommended. This way you can win some ELO points. ** Abandon the game. Players out of time will automatically accept to abandon the game. In this case you won't win any ELO points (but the player who left the game will lose some). ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. a9184ba5b4fd7f70132ed177f34629a6375e0747 1489 1453 2015-04-27T14:26:48Z Sourisdudesert 1 /* A player has to make a move but he/she doesn't. What can I do? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. 89371ded63ab2c3fd9d10ea9b6a3816e234a520a 1490 1489 2015-04-28T09:44:37Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. 66f44a704bc51f89f6535959cdfa698e4708ed91 1491 1490 2015-04-28T10:01:34Z Sourisdudesert 1 /* About board games we proposed on BGA */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA. In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. d5d92c6249c6ce4d18c52c12afe4a6ecff2fb102 1492 1491 2015-04-28T10:11:37Z Sourisdudesert 1 /* How do we select games that are on BGA? Why the game XXX is not on BGA? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. a96edc3d0a837b5a8a9f1b836627d38252fada7f 1493 1492 2015-04-28T10:15:34Z Sourisdudesert 1 /* How do we select games that are on BGA? Why the game XXX is not on BGA? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account "Most wanted games" list? When these games will be on BGA? === You should read the previous question ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refuses), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. b3a205488ae41a6aff6187bbcea1c44eee6b965e 1494 1493 2015-04-28T10:18:27Z Sourisdudesert 1 /* Are you taking into account "Most wanted games" list? When these games will be on BGA? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account "Most wanted games" list? When these games will be on BGA? === You should read the previous question ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refuses), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why some games has expansions on BGA and some hasn't? === You should read first the previous question ("how do we select games that are on BGA?"). Game expansion follows the same steps than games. There can be various reasons why a game publisher don't want the expansion online, and sometimes we don't find a developer that have the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. e4cff16660fb42e0b9f225a401b753c984a2cfbc 1495 1494 2015-04-28T10:22:04Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account "Most wanted games" list? When these games will be on BGA? === You should read the previous question ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refuses), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why some games has expansions on BGA and some hasn't? === You should read first the previous question ("how do we select games that are on BGA?"). Game expansion follows the same steps than games. There can be various reasons why a game publisher don't want the expansion online, and sometimes we don't find a developer that have the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. 25f1f65d2af6f73eac16b30d22f77e39296fc0c7 1496 1495 2015-04-28T10:25:43Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account "Most wanted games" list? When these games will be on BGA? === You should read the previous question ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refuses), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why some games has expansions on BGA and some hasn't? === You should read first the previous question ("how do we select games that are on BGA?"). Game expansion follows the same steps than games. There can be various reasons why a game publisher don't want the expansion online, and sometimes we don't find a developer that have the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this is the best approach for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allow us to finance the time we spent on BGA. ae1aacbf2a3c682ab1f7ac74a6125a2b621132ea 1498 1496 2015-04-28T11:59:21Z Sourisdudesert 1 /* About the BGA team */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account "Most wanted games" list? When these games will be on BGA? === You should read the previous question ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refuses), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why some games has expansions on BGA and some hasn't? === You should read first the previous question ("how do we select games that are on BGA?"). Game expansion follows the same steps than games. There can be various reasons why a game publisher don't want the expansion online, and sometimes we don't find a developer that have the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this is the best approach for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allow us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 8107f0eb55b6fda27c864366eb1aefd8710fd9dd 1499 1498 2015-04-28T12:04:39Z Sourisdudesert 1 /* I'm a game publisher: why would I like to have my game on Board Game Arena? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account "Most wanted games" list? When these games will be on BGA? === You should read the previous question ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refuses), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why some games has expansions on BGA and some hasn't? === You should read first the previous question ("how do we select games that are on BGA?"). Game expansion follows the same steps than games. There can be various reasons why a game publisher don't want the expansion online, and sometimes we don't find a developer that have the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licence" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes this is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. This is also possible to bring your own developer: of course it accelerates the process a lot! == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this is the best approach for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allow us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) b1af24322358bf1dcc51848f18dacc5d035bb4d9 1500 1499 2015-04-28T12:05:50Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account "Most wanted games" list? When these games will be on BGA? === You should read the previous question ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refuses), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why some games has expansions on BGA and some hasn't? === You should read first the previous question ("how do we select games that are on BGA?"). Game expansion follows the same steps than games. There can be various reasons why a game publisher don't want the expansion online, and sometimes we don't find a developer that have the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licence" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes this is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. This is also possible to bring your own developer: of course it accelerates the process a lot! == Issues with BGA == todo == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this is the best approach for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allow us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 493107150f37c22e3e3b42adf58baa675c94ad11 1501 1500 2015-04-28T12:06:06Z Sourisdudesert 1 /* What can I do if I have an issue with the website? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account "Most wanted games" list? When these games will be on BGA? === You should read the previous question ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refuses), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why some games has expansions on BGA and some hasn't? === You should read first the previous question ("how do we select games that are on BGA?"). Game expansion follows the same steps than games. There can be various reasons why a game publisher don't want the expansion online, and sometimes we don't find a developer that have the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licence" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes this is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. This is also possible to bring your own developer: of course it accelerates the process a lot! == Issues with BGA == todo == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this is the best approach for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allow us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 772172e15858af5a10f43c028789931b46ca17a3 Gamehelptakenoko 0 104 1454 1235 2015-04-09T07:43:40Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Bamboo and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to any plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a straight line and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a straight line and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Improvements can only be placed on plots with no bamboo. There can only be 1 improvement on a plot and once placed cannot be changed. To place an improvement as soon as the plot is placed, pick the improvement first. Irrigation channels must be between two plots. When a plot is irrigated for the first time it grows bamboo. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. The gardener grows bamboo on his plot and all adjacent irrigated plots of the same color. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green * 9 yellow * 7 pink ===List of objectives=== '''Plot Objectives''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts '''Gardener Objectives''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts '''Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) 452b431d80bba03066384e550eb951e6d47c5d20 1455 1454 2015-04-09T08:39:03Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Bamboo and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a <B>straight line</B> and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a <B>straight line</B> and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the plots beside the pond are considered to be irrigated automatically). When a plot is irrigated for the <B>first</B> time it grows bamboo. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''Plot Objectives''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} '''Gardener Objectives''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} 9b83d3cf6a34a9eb03cfe35d675a92a677514d85 1456 1455 2015-04-09T08:40:44Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a <B>straight line</B> and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a <B>straight line</B> and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the plots beside the pond are considered to be irrigated automatically). When a plot is irrigated for the <B>first</B> time it grows bamboo. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''Plot Objectives''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} '''Gardener Objectives''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} 290fecb6528a89d0216577fa7a036fbba143282b 1457 1456 2015-04-09T08:50:27Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a <B>straight line</B> and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a <B>straight line</B> and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the plots beside the pond are considered to be irrigated automatically). When a plot is irrigated for the <B>first</B> time it grows bamboo. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''Plot Objectives''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal *note |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *note: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card '''Gardener Objectives''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} d7147304e25f8b343dfae8c8fa02fc786fa8177d 1458 1457 2015-04-09T08:52:02Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a <B>straight line</B> and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a <B>straight line</B> and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the plots beside the pond are considered to be irrigated automatically). When a plot is irrigated for the <B>first</B> time it grows bamboo. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal *note |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *note: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} 9fe6bf04b7e88925f1762c66117a199bbdb9d6d6 1459 1458 2015-04-09T09:04:24Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a <B>straight line</B> and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a <B>straight line</B> and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the plots beside the pond are considered to be irrigated automatically). When a plot is irrigated for the <B>first</B> time it grows bamboo. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal *note |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} 389eb96a6e04a75881a3a2124ff1fc9b686f0401 1460 1459 2015-04-09T09:05:37Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a <B>straight line</B> and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a <B>straight line</B> and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the plots beside the pond are considered to be irrigated automatically). When a plot is irrigated for the <B>first</B> time it grows bamboo. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} fba98772112c768b2c3946826dbdb3661fa42c44 1461 1460 2015-04-09T09:07:23Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a <B>straight line</B> and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a <B>straight line</B> and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the plots beside the pond are considered to be irrigated automatically). When a plot is irrigated for the <B>first</B> time it grows bamboo. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can rotate the card while looking at the board, but that might give away what objective you are holding ....) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} 388de89addbea493c1bcec52ef5be2fc72f7fb41 1462 1461 2015-04-09T09:07:56Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a <B>straight line</B> and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a <B>straight line</B> and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the plots beside the pond are considered to be irrigated automatically). When a plot is irrigated for the <B>first</B> time it grows bamboo. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can rotate the card while looking at the board, but that might give away what objective you are holding!) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} de25463cad66ae692275d61f3c4f9f9288d43fd2 1463 1462 2015-04-09T09:19:57Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a <B>straight line</B> and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a <B>straight line</B> and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the plots beside the pond are considered to be irrigated automatically). A plot with a watershed improvement is also considered to be irrigated automatically for plot and gardening purposes, but not for placing irrigation channels. Irrigation channels must always have a connection path back to the central pond either directly or via previous irrigation channels. When a plot is irrigated for the <B>first</B> time it grows bamboo. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can rotate the card while looking at the board, but that might give away what objective you are holding!) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} 5b5997545397b959f4cb402f3b250ddda6f51cdd 1464 1463 2015-04-09T09:21:54Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a <B>straight line</B> and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a <B>straight line</B> and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Placing an improvement from your reserve does NOT use up one of your actions for that turn. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the plots beside the pond are considered to be irrigated automatically). Placing an irrigation channel from your reserve does NOT use up one of your actions for that turn. A plot with a watershed improvement is also considered to be irrigated automatically for plot and gardening purposes, but not for placing irrigation channels. Irrigation channels must always have a connection path back to the central pond either directly or via previous irrigation channels. When a plot is irrigated for the <B>first</B> time it grows bamboo. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can rotate the card while looking at the board, but that might give away what objective you are holding!) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} b4e1bb659eab594f28f1faa1326c1be2e8cf4511 1465 1464 2015-04-09T09:23:48Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store for later use. * '''Gardener''' - Move the gardener any number of tiles in a <B>straight line</B> and then grow bamboo. * '''Panda''' - Move the panda any number of tiles in a <B>straight line</B> and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Placing an improvement from your reserve does NOT use up one of your actions for that turn. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the 6 plots directly beside the pond are considered to be irrigated automatically). Placing an irrigation channel from your reserve does NOT use up one of your actions for that turn. A plot with a watershed improvement is also considered to be irrigated automatically for plot and gardening purposes, but not for placing irrigation channels. Irrigation channels must always have a connection path back to the central pond either directly or via previous irrigation channels. When a plot is irrigated for the <B>first</B> time it grows bamboo. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can rotate the card while looking at the board, but that might give away what objective you are holding!) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} dc83d3b674554aed32991d13b2522dd9f94c700c 1466 1465 2015-04-09T09:26:06Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one in the garden * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store it in your reserve for later use. * '''Gardener''' - Move the gardener any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then grow bamboo. * '''Panda''' - Move the panda any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Placing an improvement from your reserve does NOT use up one of your actions for that turn. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the 6 plots directly beside the pond are considered to be irrigated automatically). Placing an irrigation channel from your reserve does NOT use up one of your actions for that turn. A plot with a watershed improvement is also considered to be irrigated automatically for plot and gardening purposes, but not for placing irrigation channels. Irrigation channels must always have a connection path back to the central pond either directly or via previous irrigation channels. When a plot is irrigated for the <B>first</B> time it grows bamboo. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can rotate the card while looking at the board, but that might give away what objective you are holding!) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} c72e2112f466128945d5bc4875048c1c3d8bdab1 1467 1466 2015-04-09T09:27:58Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one in the garden * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store it in your reserve for later use. * '''Gardener''' - Move the gardener any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then grow bamboo. * '''Panda''' - Move the panda any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Placing an improvement from your reserve does NOT use up one of your actions for that turn. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the 6 plots directly beside the pond are considered to be irrigated automatically). Placing an irrigation channel from your reserve does NOT use up one of your actions for that turn. When a plot is irrigated for the <B>first</B> time it grows bamboo. A plot with a watershed improvement is also considered to be irrigated automatically for plot and gardening purposes, but not for placing irrigation channels. Irrigation channels must always have a connection path back to the central pond either directly or via previous irrigation channels. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. Bamboo stalks grow up to a maximum height of 4. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives The first player to complete the required number of objectives triggers the final round and scores 2 bonus points. The other players have a final turn. The highest score wins, the tie breaker is number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can rotate the card while looking at the board, but that might give away what objective you are holding!) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} 50682d55b39ac6f4b782f6a1a78f3705bfef609d 1468 1467 2015-04-09T09:42:07Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one in the garden * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store it in your reserve for later use. * '''Gardener''' - Move the gardener any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then grow bamboo. * '''Panda''' - Move the panda any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Placing an improvement from your reserve does NOT use up one of your actions for that turn. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the 6 plots directly beside the pond are considered to be irrigated automatically). Placing an irrigation channel from your reserve does NOT use up one of your actions for that turn. When a plot is irrigated for the <B>first</B> time it grows bamboo. A plot with a watershed improvement is also considered to be irrigated automatically for plot and gardening purposes, but not for placing irrigation channels. Irrigation channels must always have a connection path back to the central pond either directly or via previous irrigation channels. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. Bamboo stalks grow up to a maximum height of 4. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Completing objectives''' '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives A player can complete any number of objectives any time during their turn. They may do so if their objective card is matched by the conditions of the garden at that time (for plot and gardener objectives), or if a player has the correct amount of bamboo for panda objectives. A completed objective is never lost, even if the garden conditions change later in the game. Plot objectives are completed when the garden configuration shown on the card is reflected in the garden with all the component plots irrigated. Gardener objectives are completed when a matching bamboo towers of the matching colour and base is reflected in the garden. Panda objectives are completed by returning the correct amount of bamboo from your reserve to the supply. The first player to complete the required number of objectives triggers the final round and receives the emperor card, scoring 2 bonus points. The other players have a final turn. After they finish, the highest score wins. If the score is tied, the tie breaker is the number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can rotate the card while looking at the board, but that might give away what objective you are holding!) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} ed9306ea34a4ec1e39b74f238aad537143abfd86 1469 1468 2015-04-09T09:45:34Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one in the garden * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store it in your reserve for later use. * '''Gardener''' - Move the gardener any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then grow bamboo. * '''Panda''' - Move the panda any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. If the selected plot or gardener objective is already reflected in the current state of the garden, the objective is placed at the bottom of the deck and a subsequent objective may be selected. This is the only situation where an action can be cancelled, and a different action can be taken. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Placing an improvement from your reserve does NOT use up one of your actions for that turn. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the 6 plots directly beside the pond are considered to be irrigated automatically). Placing an irrigation channel from your reserve does NOT use up one of your actions for that turn. When a plot is irrigated for the <B>first</B> time it grows bamboo. A plot with a watershed improvement is also considered to be irrigated automatically for plot and gardening purposes, but not for placing irrigation channels. Irrigation channels must always have a connection path back to the central pond either directly or via previous irrigation channels. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. Bamboo stalks grow up to a maximum height of 4. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Completing objectives''' '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives A player can complete any number of objectives any time during their turn. They may do so if their objective card is matched by the conditions of the garden at that time (for plot and gardener objectives), or if a player has the correct amount of bamboo for panda objectives. A completed objective is never lost, even if the garden conditions change later in the game. Plot objectives are completed when the garden configuration shown on the card is reflected in the garden with all the component plots irrigated. Gardener objectives are completed when a matching bamboo towers of the matching colour and base is reflected in the garden. Panda objectives are completed by returning the correct amount of bamboo from your reserve to the supply. The first player to complete the required number of objectives triggers the final round and receives the emperor card, scoring 2 bonus points. The other players have a final turn. After they finish, the highest score wins. If the score is tied, the tie breaker is the number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can rotate the card while looking at the board, but that might give away what objective you are holding!) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} e0c38ab8809f64eed723d005a63e4d95b22b922c 1470 1469 2015-04-09T09:46:42Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one in the garden * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store it in your reserve for later use. * '''Gardener''' - Move the gardener any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then grow bamboo. * '''Panda''' - Move the panda any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. If the selected plot or gardener objective is already reflected in the current state of the garden, the objective is placed at the bottom of the deck and a subsequent objective may be selected. This is the only situation where an action can be cancelled, and a different action can be taken. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. There can only be 1 improvement on a plot. Thus, improvements can only be placed on plots with no bamboo or any other improvement. Once an improvement is placed, it cannot be changed. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Placing an improvement from your reserve does NOT use up one of your actions for that turn. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the 6 plots directly beside the pond are considered to be irrigated automatically). Placing an irrigation channel from your reserve does NOT use up one of your actions for that turn. When a plot is irrigated for the <B>first</B> time it grows bamboo. A plot with a watershed improvement is also considered to be irrigated automatically for plot and gardening purposes, but not for placing irrigation channels. Irrigation channels must always have a connection path back to the central pond either directly or via previous irrigation channels. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. Bamboo stalks grow up to a maximum height of 4. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Completing objectives''' '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives A player can complete any number of objectives any time during their turn. They may do so if their objective card is matched by the conditions of the garden at that time (for plot and gardener objectives), or if a player has the correct amount of bamboo for panda objectives. A completed objective is never lost, even if the garden conditions change later in the game. Plot objectives are completed when the garden configuration shown on the card is reflected in the garden with all the component plots irrigated. Gardener objectives are completed when a matching bamboo towers of the matching colour and base is reflected in the garden. Panda objectives are completed by returning the correct amount of bamboo from your reserve to the supply. The first player to complete the required number of objectives triggers the final round and receives the Emperor card, scoring 2 bonus points. The other players have a final turn. After they finish, the highest score wins. If the score is tied, the tie breaker is the number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can rotate the card while looking at the board, but that might give away what objective you are holding!) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} b16829318244bd6337638ea36aa328526ad89508 1471 1470 2015-04-09T09:52:30Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one in the garden * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store it in your reserve for later use. * '''Gardener''' - Move the gardener any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then grow bamboo. * '''Panda''' - Move the panda any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. If the selected plot or gardener objective is already reflected in the current state of the garden, the objective is placed at the bottom of the deck and a subsequent objective may be selected. This is the only situation where an action can be cancelled, and a different action can be taken. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Improvements can only be placed on plots with no bamboo or any other improvement (completely blank). Once an improvement is placed, it cannot be changed. Placing an improvement from your reserve does NOT use up one of your actions for that turn. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the 6 plots directly beside the pond are considered to be irrigated automatically). Placing an irrigation channel from your reserve does NOT use up one of your actions for that turn. When a plot is irrigated for the <B>first</B> time it grows bamboo. A plot with a watershed improvement is also considered to be irrigated automatically for plot and gardening purposes, but not for placing irrigation channels. Irrigation channels must always have a connection path back to the central pond either directly or via previous irrigation channels. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. Bamboo stalks grow up to a maximum height of 4. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Completing objectives''' '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives A player can complete any number of objectives any time during their turn. They may do so if their objective card is matched by the conditions of the garden at that time (for plot and gardener objectives), or if a player has the correct amount of bamboo for panda objectives. A completed objective is never lost, even if the garden conditions change later in the game. Plot objectives are completed when the garden configuration shown on the card is reflected in the garden with all the component plots irrigated. Gardener objectives are completed when a matching bamboo towers of the matching colour and base is reflected in the garden. Panda objectives are completed by returning the correct amount of bamboo from your reserve to the supply. The first player to complete the required number of objectives triggers the final round and receives the Emperor card, scoring 2 bonus points. The other players have a final turn. After they finish, the highest score wins. If the score is tied, the tie breaker is the number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can rotate the card while looking at the board, but that might give away what objective you are holding!) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} 1d05a5a77a0557021bbeee4f50bdbe0bffc51903 1472 1471 2015-04-09T09:53:58Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one in the garden * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store it in your reserve for later use. * '''Gardener''' - Move the gardener any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then grow bamboo. * '''Panda''' - Move the panda any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. If the selected plot or gardener objective is already reflected in the current state of the garden, the objective is placed at the bottom of the deck and a subsequent objective may be selected. This is the only situation where an action can be cancelled, and a different action can be taken. Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Improvements can only be placed on plots with no bamboo or any other improvement (completely blank). Once an improvement is placed, it cannot be changed. Placing an improvement from your reserve does NOT use up one of your actions for that turn. Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the 6 plots directly beside the pond are considered to be irrigated automatically). Placing an irrigation channel from your reserve does NOT use up one of your actions for that turn. When a plot is irrigated for the <B>first</B> time it grows bamboo. A plot with a watershed improvement is also considered to be irrigated automatically for plot and gardening purposes, but not for placing irrigation channels. Irrigation channels must always have a connection path back to the central pond either directly or via previous irrigation channels. The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. Bamboo stalks grow up to a maximum height of 4. The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. '''Completing objectives''' '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives A player can complete any number of objectives any time during their turn. They may do so if their objective card is matched by the conditions of the garden at that time (for plot and gardener objectives), or if a player has the correct amount of bamboo for panda objectives. A completed objective is never lost, even if the garden conditions change later in the game. Plot objectives are completed when the garden configuration shown on the card is reflected in the garden with all the component plots irrigated. Gardener objectives are completed when a matching bamboo towers of the matching colour and base is reflected in the garden. Panda objectives are completed by returning the matching amount of bamboo from your reserve to the supply. The first player to complete the required number of objectives triggers the final round and receives the Emperor card, scoring 2 bonus points. The other players have a final turn. After they finish, the highest score wins. If the score is tied, the tie breaker is the number of points on panda objectives. If the score is still tied then all tied players win. ===Plot Distribution=== 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can rotate the card while looking at the board, but that might give away what objective you are holding!) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} 065a9974a0b1b20deeb4cc9f13dbc3a177892780 1473 1472 2015-04-09T09:57:59Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one in the garden * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store it in your reserve for later use. * '''Gardener''' - Move the gardener any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then grow bamboo. * '''Panda''' - Move the panda any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. If the selected plot or gardener objective is already reflected in the current state of the garden, the objective is placed at the bottom of the deck and a subsequent objective may be selected. This is the only situation where an action can be cancelled, and a different action can be taken. '''Plot Distribution''' 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. '''Improvements''' Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Improvements can only be placed on plots with no bamboo or any other improvement (completely blank). Once an improvement is placed, it cannot be changed. Placing an improvement from your reserve does NOT use up one of your actions for that turn. '''Irrigation Channels''' Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the 6 plots directly beside the pond are considered to be irrigated automatically). Placing an irrigation channel from your reserve does NOT use up one of your actions for that turn. When a plot is irrigated for the <B>first</B> time it grows bamboo. A plot with a watershed improvement is also considered to be irrigated automatically for plot and gardening purposes, but not for placing irrigation channels. Irrigation channels must always have a connection path back to the central pond either directly or via previous irrigation channels. '''Growing Bamboo''' The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. Bamboo stalks grow up to a maximum height of 4. '''Eating Bamboo''' The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. ===Completing objectives=== '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives A player can complete any number of objectives any time during their turn. They may do so if their objective card is matched by the conditions of the garden at that time (for plot and gardener objectives), or if a player has the correct amount of bamboo for panda objectives. A completed objective is never lost, even if the garden conditions change later in the game. Plot objectives are completed when the garden configuration shown on the card is reflected in the garden with all the component plots irrigated. Gardener objectives are completed when a matching bamboo towers of the matching colour and base is reflected in the garden. Panda objectives are completed by returning the matching amount of bamboo from your reserve to the supply. The first player to complete the required number of objectives triggers the final round and receives the Emperor card, scoring 2 bonus points. The other players have a final turn. After they finish, the highest score wins. If the score is tied, the tie breaker is the number of points on panda objectives. If the score is still tied then all tied players win. ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can rotate the card while looking at the board, but that might give away what objective you are holding!) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} f6b17027007ac00824861c5163e69bd509d97ecd 1474 1473 2015-04-09T09:59:02Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank, if no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one in the garden * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store it in your reserve for later use. * '''Gardener''' - Move the gardener any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then grow bamboo. * '''Panda''' - Move the panda any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. If the selected plot or gardener objective is already reflected in the current state of the garden, the objective is placed at the bottom of the deck and a subsequent objective may be selected. This is the only situation where an action can be cancelled, and a different action can be taken. '''Plot Distribution''' 28 plots in total consisting of: * 12 green plots * 9 yellow plots * 7 pink plots Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. '''Improvements''' Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Improvements can only be placed on plots with no bamboo or any other improvement (completely blank). Once an improvement is placed, it cannot be changed. Placing an improvement from your reserve does NOT use up one of your actions for that turn. '''Irrigation Channels''' Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the 6 plots directly beside the pond are considered to be irrigated automatically). Placing an irrigation channel from your reserve does NOT use up one of your actions for that turn. When a plot is irrigated for the <B>first</B> time it grows bamboo. A plot with a watershed improvement is also considered to be irrigated automatically for plot and gardening purposes, but not for placing irrigation channels. Irrigation channels must always have a connection path back to the central pond either directly or via previous irrigation channels. '''Growing Bamboo''' The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. Bamboo stalks grow up to a maximum height of 4. '''Eating Bamboo''' The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. ===Completing objectives=== '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives A player can complete any number of objectives any time during their turn. They may do so if their objective card is matched by the conditions of the garden at that time (for plot and gardener objectives), or if a player has the correct amount of bamboo for panda objectives. A completed objective is never lost, even if the garden conditions change later in the game. Plot objectives are completed when the garden configuration shown on the card is reflected in the garden with all the component plots irrigated. Gardener objectives are completed when a matching bamboo towers of the matching colour and base is reflected in the garden. Panda objectives are completed by returning the matching amount of bamboo from your reserve to the supply. The first player to complete the required number of objectives triggers the final round and receives the Emperor card, scoring 2 bonus points. The other players have a final turn. After they finish, the highest score wins. If the score is tied, the tie breaker is the number of points on panda objectives. If the score is still tied then all tied players win. ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can rotate the card while looking at the board, but that might give away what objective you are holding!) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} 160da6b4b9ea15aa0a73cdb4c9e87999f9d98db1 1475 1474 2015-04-09T15:58:59Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank of 3 watersheds, 3 fertilizers, and 3 enclosures. If no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one in the garden * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store it in your reserve for later use. * '''Gardener''' - Move the gardener any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then grow bamboo. * '''Panda''' - Move the panda any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. If the selected plot or gardener objective is already reflected in the current state of the garden, the objective is placed at the bottom of the deck and a subsequent objective may be selected. This is the only situation where an action can be cancelled, and a different action can be taken. '''Plot Distribution''' 28 plots in total consisting of: * 12 green plots: 5 blank, 2 watershed, 2 fertilizer, 2 enclosure * 9 yellow plots: 5 blank, 1 watershed, 1 fertilizer, 1 enclosure * 7 pink plots: 4 blank, 1 watershed, 1 fertilizer, 1 enclosure Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. '''Improvements''' Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Improvements can only be placed on plots with no bamboo or any other improvement (completely blank). Once an improvement is placed, it cannot be changed. Placing an improvement from your reserve does NOT use up one of your actions for that turn. '''Irrigation Channels''' Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the 6 plots directly beside the pond are considered to be irrigated automatically). Placing an irrigation channel from your reserve does NOT use up one of your actions for that turn. When a plot is irrigated for the <B>first</B> time it grows bamboo. A plot with a watershed improvement is also considered to be irrigated automatically for plot and gardening purposes, but not for placing irrigation channels. Irrigation channels must always have a connection path back to the central pond either directly or via previous irrigation channels. '''Growing Bamboo''' The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. Bamboo stalks grow up to a maximum height of 4. '''Eating Bamboo''' The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. ===Completing objectives=== '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives A player can complete any number of objectives any time during their turn. They may do so if their objective card is matched by the conditions of the garden at that time (for plot and gardener objectives), or if a player has the correct amount of bamboo for panda objectives. A completed objective is never lost, even if the garden conditions change later in the game. Plot objectives are completed when the garden configuration shown on the card is reflected in the garden with all the component plots irrigated. Gardener objectives are completed when a matching bamboo towers of the matching colour and base is reflected in the garden. Panda objectives are completed by returning the matching amount of bamboo from your reserve to the supply. The first player to complete the required number of objectives triggers the final round and receives the Emperor card, scoring 2 bonus points. The other players have a final turn. After they finish, the highest score wins. If the score is tied, the tie breaker is the number of points on panda objectives. If the score is still tied then all tied players win. ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can rotate the card while looking at the board, but that might give away what objective you are holding!) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} 773a002b58f2171cf549a3e0a22c3c7cc1beac7f 1476 1475 2015-04-09T16:05:39Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to earn points by completing objectives. There are three types of objectives: Plot, Gardener and Panda. Players start with one of each type. Each turn consists of 2 steps: # Determine weather (except in the players first turn) # Perform 2 different actions, place any number of improvements and irrigation channels, and complete any number of objectives '''Weather types (always optional)''' * '''Sun''' - take a 3rd action * '''Rain''' - grow 1 bamboo on any irrigated plot * '''Wind''' - may take two identical actions this turn * '''Storm''' - move panda to <B>any</B> plot and he eats a bamboo as normal * '''Clouds''' - take an improvement chip from the bank of 3 watersheds, 3 fertilizers, and 3 enclosures. If no chips are available, choose 1 of the other 4 types of weather * '''Question mark''' - choose any 1 of the 5 types of weather '''Actions''' * '''Plots''' - draw 3 plot tiles and place one in the garden * '''Irrigation''' - Take an irrigation channel from the reserve. Either place it immediately or store it in your reserve for later use. * '''Gardener''' - Move the gardener any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then grow bamboo. * '''Panda''' - Move the panda any number of garden tiles in a <B>straight line</B> (can not jump over gaps) and then eat a bamboo section. The bamboo is then placed in your reserve. * '''Objective''' - Take another objective card from one of the 3 decks. There is a hand limit of 5 cards. If the selected plot or gardener objective is already reflected in the current state of the garden, the objective is placed at the bottom of the deck and a subsequent objective may be selected. This is the only situation where an action can be cancelled, and a different action can be taken. '''Plot Distribution''' 28 plots in total consisting of: * 12 green plots: 5 blank, 2 watershed, 2 fertilizer, 2 enclosure * 9 yellow plots: 5 blank, 1 watershed, 1 fertilizer, 1 enclosure * 7 pink plots: 4 blank, 1 watershed, 1 fertilizer, 1 enclosure Plots can only be placed adjacent to the pond or in a spot next to 2 other existing plots. '''Improvements''' Improvements need to have been picked up during a previous Clouds weather action in order to be placed as soon as a plot is added to the garden. Once you have an improvement in your reserve, click on the desired improvement from the panel on the right (a red box should appear around it) and then select the plot on the board where you wish to place the improvement. Improvements can only be placed on plots with no bamboo or any other improvement (completely blank). Once an improvement is placed, it cannot be changed. Placing an improvement from your reserve does NOT use up one of your actions for that turn. '''Irrigation Channels''' Irrigation channels picked up in a previous Irrigation action may be placed on the board at any time during your turn. Once you have an irrigation channel in your reserve, click on the channel from your panel on the right (a red box should appear around it) and then place the irrigation channel between any two plots (the game allows you to place an irrigation beside the pond, but that is a wasted move as any of the 6 plots directly beside the pond are considered to be irrigated automatically). Placing an irrigation channel from your reserve does NOT use up one of your actions for that turn. When a plot is irrigated for the <B>first</B> time it grows bamboo. A plot with a watershed improvement is also considered to be irrigated automatically for plot and gardening purposes, but not for placing irrigation channels. Irrigation channels must always have a connection path back to the central pond either directly or via previous irrigation channels. '''Growing Bamboo''' The gardener grows bamboo on the plot that he moves to and all adjacent <B>irrigated</B> plots of the <B>same color</B>. Bamboo stalks normally grow 1 taller with every valid gardener or Rain weather action. However, if the plot has a fertilizer improvement, the bamboo stalk will grow 2 taller with every valid garderner or Rain weather action. Bamboo stalks grow up to a maximum height of 4. '''Eating Bamboo''' The panda normally eats 1 bamboo from any plot that he moves to either using the Panda action or the Storm weather action. However, the panda can NOT eat any bamboo from a plot with an enclosure improvement. ===Completing objectives=== '''Game ends''' when a certain number of objectives have been completed. * 2 players - 9 objectives * 3 players - 8 objectives * 4 players - 7 objectives A player can complete any number of objectives any time during their turn. They may do so if their objective card is matched by the conditions of the garden at that time (for plot and gardener objectives), or if a player has the correct amount of bamboo for panda objectives. A completed objective is never lost, even if the garden conditions change later in the game. Plot objectives are completed when the garden configuration shown on the card is reflected in the garden with all the component plots irrigated. Gardener objectives are completed when a matching bamboo towers of the matching colour and base is reflected in the garden. Panda objectives are completed by returning the matching amount of bamboo from your reserve to the supply. The first player to complete the required number of objectives triggers the final round and receives the Emperor card, scoring 2 bonus points. The other players have a final turn. After they finish, the highest score wins. If the score is tied, the tie breaker is the number of points on panda objectives. If the score is still tied then all tied players win. ===List of objectives=== '''I. Plot Objectives (15 total)''' Straights, curves and triangles all consist of 3 tiles. Diamonds consist of 4 tiles. * Green Triangle - 2 pts * Green Straight - 2 pts * Green Curve - 2 pts * Green Diamond - 3 pts * Yellow Triangle - 3 pts * Yellow Straight - 3 pts * Yellow Curve - 3 pts * Yellow Diamond - 4 pts * Pink Triangle - 4 pts * Pink Straight - 4 pts * Pink Curve - 4 pts * Pink Diamond - 5 pts * Yellow/Green Diamond - 3 pts * Pink/Green Diamond - 4 pts * Yellow/Pink Diamond - 5 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="100" | Plot Colour ! align="center" width="50" | Triangle of 3 ! align="center" width="50" | Straight of 3 ! align="center" width="50" | Bend of 3 ! align="center" width="50" | Diamond of 4 ! align="center" width="125" | Diamond of 4 with NW-SE diagonal<BR> (see note below) |- | align="center" | Green | align="center" | 2 pts | align="center" | 2 pts | align="center" | 2 pts | align="center" | 3 pts | align="center" | |- | align="center" | Yellow | align="center" | 3 pts | align="center" | 3 pts | align="center" | 3 pts | align="center" | 4 pts | align="center" | |- | align="center" | Pink | align="center" | 4 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | |- | align="center" | Green / Yellow | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 3 pts |- | align="center" | Green / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 4 pts |- | align="center" | Yellow / Pink | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 5 pts |- |} *<B>NOTE</B>: as long as the diagonal between the 2 colours can be seen to go from top-left to bottom-right, the plot can be sideways or upside down with respect to what is seen on the objective card (you can turn your head sideways to check since you are playing online and, unlike live play, you won't give away information about what objective you are holding!) '''II. Gardener Objectives (15 total)''' * 4 Tall on Green w/ Fertilizer - 3 pts * 4 Tall on Green w/ Enclosure - 4 pts * 4 Tall on Green w/ Watershed - 4 pts * 4 Tall on Green w/ NO Improvements - 5 pts * 3 Tall on 4 Greens - 8 pts * 4 Tall on Yellow w/ Fertilizer - 4 pts * 4 Tall on Yellow w/ Enclosure - 5 pts * 4 Tall on Yellow w/ Watershed - 5 pts * 4 Tall on Yellow w/ NO Improvements - 6 pts * 3 Tall on 3 Yellows - 7 pts * 4 Tall on Pink w/ Fertilizer - 5 pts * 4 Tall on Pink w/ Enclosure - 6 pts * 4 Tall on Pink w/ Watershed - 6 pts * 4 Tall on Pink w/ NO Improvements - 7 pts * 3 Tall on 2 Pinks - 6 pts {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="50" | Bamboo Colour ! align="center" width="50" | Height ! align="center" width="50" | Fertilizer Base ! align="center" width="50" | Watershed Base ! align="center" width="50" | Enclosure Base ! align="center" width="50" | Blank Base ! align="center" width="50" | Any 2 Pink Bases ! align="center" width="50" | Any 3 Yellow Bases ! align="center" width="50" | Any 4 Green Bases |- | align="center" | Green | align="center" | 4-high | align="center" | 3 pts | align="center" | 4 pts | align="center" | 4 pts | align="center" | 5 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Green | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 8 pts |- | align="center" | Yellow | align="center" | 4-high | align="center" | 4 pts | align="center" | 5 pts | align="center" | 5 pts | align="center" | 6 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Yellow | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 7 pts | align="center" | |- | align="center" | Pink | align="center" | 4-high | align="center" | 5 pts | align="center" | 6 pts | align="center" | 6 pts | align="center" | 7 pts | align="center" | | align="center" | | align="center" | |- | align="center" | Pink | align="center" | 3-high | align="center" | | align="center" | | align="center" | | align="center" | | align="center" | 6 pts | align="center" | | align="center" | |- |} '''III. Panda Objectives (15 total)''' * 2 Green - 3 points (x5 cards) * 2 Yellow - 4 pts (x4) * 2 Pink - 5 pts (x3) * 1 Green, 1 Yellow, 1 Pink - 6 pts (x3) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="150" | Panda Objective ! align="center" width="50" | Number Available ! align="center" width="50" | Point Value |- | align="center" | Green Bamboo x2 | align="center" | 5 | align="center" | 3 pts |- | align="center" | Yellow Bamboo x2 | align="center" | 4 | align="center" | 4 pts |- | align="center" | Pink Bamboo x2 | align="center" | 3 | align="center" | 5 pts |- | align="center" | Green Bamboo x1,<BR> Yellow Bamboo x1,<BR> Pink Bamboo x1 | align="center" | 3 | align="center" | 6 pts |} b505b242dd4f6bd9c81e9c153115817721464e7c Gamehelpthejellymonsterlab 0 141 1477 1359 2015-04-17T22:13:48Z Yakker 8642 Clarification of how to move cards between hand and lab. This caused confusion when I played. Also a few spelling errors fixed. wikitext text/x-wiki In The Jelly Monster Lab you are a scientist trying to make the best jelly monsters. In order to do it so, you need to move through the labs, trying to find the parts you need to make your monsters. At the beginning, every player starts with two experiments. Every experiment shows a monster made with a colored body (blue, red, pink or green), eyes (1, 2 or 3) and a mouth (happy or sad) and a lab where you must make it. The parts are spread out over the six labs, so you move to them, and grab the parts you need to make your monsters, but you cannot have more than 5 cards in your hand. To move cards to and from your hand, click on the card then click the arrows to the right of the "Your hand" section. Once you have your experiment card and the parts, move to the lab indicated by the experiment card and leave all there (the experiment card and the parts). When other player come to visit that lab, it'll find your monster and then, it will be yours. While you're moving through the labs, you're leaving trails in order to know which player has been the last visiting it. If you move to a lab with a trail, there may be a monster of the owner of the trail. In addition, you can't move to a lab you were the last visit, so you need to program your moves to have all the parts of the experiment before you arrive to the lab where you must leave it with all the parts in your hand. In any time, you may want to go to the center to pick up a new experiment and make new monsters. But you'll not be able to go to the center if you just came from there (your meeple shows laid down) and if you have the maximum cards in hand (five). When a player has 4 monsters done, the center is open to close the game. Any player who goes there, finishes the game. Every monster has an score on it, depending on how difficult is to find their parts. You can see how many parts are in the game of each type, and what are all the experiments in the guide card placed on the bottom left corner of the playboard. The player with the most score points win the game. Advice: If you have experiments, one side too low scored, or on the other side too difficult to find the parts, you can leave the experiment card in any lab, so other players can play with it, or maybe you can play with it in a later visit. 0af3fcc33d81f4a560613fce0511010bc45d1796 Gamehelppolis 0 179 1478 1384 2015-04-18T00:19:54Z Wentley 8121 /* Military Actions (cost 1 Prestige) */ wikitext text/x-wiki == Development Actions == # Create Hoplites: Only in one polis per turn; pay 1 metal (or silver) per hoplite # Create Galleys: Only in one polis per turn; pay 1 wood (or silver) per galley, then place it in adjacent sea territory (see arrow). # Create Merchants: Only in one commercial city per turn; pay 1 wood (or silver) per merchant, then place it in Trade Port. == Military Actions (cost 1 Prestige) == # Move Hoplites: Destination territory of all hoplites has to be the same; each unit is moved separately (via land or sea territories, but not both); territories controlled by opponent (with greater number of units) block movement. # Move Galleys: Destination territory of all galleys has to be the same; each unit is moved separately (only sea territories); territories controlled by opponent block movement. # Besiege Polis: Player has to control territory with at least as many hoplites as polis has Fortification. Throw the die: * If result higher than/equal to Fortification: take Polis Tile (with all projects); receive Prestige (= Fortification). * If result lower than Fortification, attacker loses 1 hoplite. If polis owned by opponent, it loses 1 Population Cube. # Collection: Must own polis in region. Take resources corresponding to number of hoplites from the region placed in Tribute Box. Place disk to show region exhausted and return hoplites. No Prestige cost for action in home region. == Political Actions == # Trade: Move one merchant via free trade route to Foreign Market and place it on available shipload: * Goods exchange (goods for wheat / silver); then increase market value (roll die; move marker right). * Purchase (silver paid for wheat); then decrease market value (roll die twice; use higher result to move marker left). # Move Proxenos: Movement via land or sea territories. Has to bribe each enemy unit with 1 silver (not to the opponent). # Redeem Proxenos: Pay 2 silver to opponent; place Proxenos in capital. # Instigate Civil War: Proxenos needed; action costs 2x Base Population (neutral polis) or 3x current Population (owned by opponent). Receive Prestige (= Population bribed, not amount of money spent). == Battle == If 8 or more units in territory after player's turn. Attacker plays 2 cards, defender tries to match formations. Card pairs are then compared: * not matching: defender loses 1 unit, attacker gains Prestige on card. * matching: no loss for defender, attacker gains Prestige difference if his value is higher. Attacker draws 2 cards; defender draws one less card for each loss suffered (maximum 2). The battle ends if: # not enough cards are left in the Combat Card deck. # one player retreats (and pays 1 Prestige to opponent). # one player has less than 2 units left. == End of the Round == # Projects: all are completed, and award immediate Prestige. # Supply: player has to pay wheat = total of Population Cubes; if insufficient, difference either paid with Prestige, or poleis are discarded. # Growth: increase Population in poleis with wheat (1:1); heed Maximum Growth and Population Maximum. Optional. # Megalopolis: 1 Prestige awarded for every polis exceeding Base Population. # Storage: halve amount of oil, wine, and wheat in storage (rounded up) # Phoros: exchange Prestige for silver (1:1). Optional. == Preparations for the next Round == Move round marker one space to the right. Remove all discs from Tribute Boxes. Place merchants back in Trade Ports. Place 3 new Project Tiles (discard remaining tiles). Draw new Event Card. == End of Game Conditions == # A player cannot supply enough wheat/Prestige to feed his capital. # A player does not have any Prestige left after “End of Round” phase. # The fourth round (5β) has been finished. == Final Score == * total of Population Cubes in all poleis, plus * current Prestige, plus * ”Prestige for Posterity” (on project tiles). 7b8108951c2e7fc9b96ba78e837ee9cc860e2db8 Gamehelpseasons 0 43 1479 1201 2015-04-18T02:53:22Z Drcocoa 8649 wikitext text/x-wiki Seasons is a game of generating points (crystals) by choosing the correct combination of dice and the activation of card powers. The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be returned to the player on the starting of each cycle. Each player can choose only one die per turn. The effects are as follows: ''Star'' - increase the maximum card player can summon (max 15) ''Elements'' - Gain an energy of the element shown (water, earth, air, fire) ''Numbers'' - Gain the number of Crystals as indicated by the number ''Square card'' - Draw a card ''Dice with frames surrounding'' - Allow user to transmute energy into crystal (depend on which part of the game is at) ''Dots'' - Indicate how fast the marker progresses through the seasons cycle Each dice will have some combination of these elements. For example, a dice may give you a water, earth and allow you to transmute, all in the same turn. There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There are 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element, and allow user to choose a card out of 2 cards (must use with draw card dice). Seasons: The board is divided into four seasons each of which have common, uncommon and rare elements. These designations tell you how likely it is that these elements will appear during each season and also tell you how much each element will transmute into during that season. Blue (Winter) - Water and Wind are Common, Fire is Uncommon, and Earth is Rare Green (Spring) - Earth and Water are Common, Wind is Uncommon, and Fire is Rare Yellow (Summer) - Fire and Earth are Common, Water is Uncommon, and Wind is Rare Red (Fall) - Wind and Fire are Common, Earth is Uncommon, and Water is Rare Example: During Green (Spring), Earth and Water are the most common and will transmute into one crystal each, Wind is uncommon and will transmute into two crystals each, Fire is rare and will transmute into three crystals each. At the end of the game the points are calculated by adding the numbers on each played card and the crystal owned and substracting 5 points for each power card remaining in hand. The player with the most victory points wins. Note: Users need to discard energy immediately if the energy is more than the slots allocated. If a card allows you to summon another card but you have no space for this second card then it (the second card) will be discarded with no refund. == Difficulty levels: == '''Apprentice wizard level''' In order to make the game easier to learn, there are “pre-constructed” sets of nine power cards. Instead of taking step 1 of the first game phase, each player gets one of these sets. '''Magician level''' Only the power cards numbered 1 to 30 are in play. These cards have easy to grasp effects and will allow you to slowly discover the world of Seasons. '''Archmage level''' All 50 kinds of power cards are in play. The cards numbered 31 through 50 have more complex effects than the basic cards, but will allow you to extend the fun of playing by discovering new effects and combinations. ef834ca847a35b07a5ae80101fedb480fdbfee6e 1480 1479 2015-04-18T02:53:45Z Drcocoa 8649 wikitext text/x-wiki Seasons is a game of generating points (crystals) by choosing the correct combination of dice and the activation of card powers. The game goes by each player separating their 9 cards into 3 packs of 3 cards. The card will be returned to the player on the starting of each cycle. Each player can choose only one die per turn. The effects are as follows: ''Star'' - increase the maximum card player can summon (max 15) ''Elements'' - Gain an energy of the element shown (water, earth, air, fire) ''Numbers'' - Gain the number of Crystals as indicated by the number ''Square card'' - Draw a card ''Dice with frames surrounding'' - Allow user to transmute energy into crystal (depend on which part of the game is at) ''Dots'' - Indicate how fast the marker progresses through the seasons cycle Each dice will have some combination of these elements. For example, a dice may give you a water, earth and allow you to transmute, all in the same turn. There is also a maximum of 3 helps provided at the cost of point deduction at the end of the game. The help will cost 5 points for the 1st time, 7 for the 2nd and 8 for the 3rd. There are 4 type of helps which include adding a star, allow user to transmute this turn with an additional crystal gained for each energy transmuted, change 2 energy into any element, and allow user to choose a card out of 2 cards (must use with draw card dice). Seasons: The board is divided into four seasons each of which have common, uncommon and rare elements. These designations tell you how likely it is that these elements will appear during each season and also tell you how much each element will transmute into during that season. Blue (Winter) - Water and Wind are Common, Fire is Uncommon, and Earth is Rare Green (Spring) - Earth and Water are Common, Wind is Uncommon, and Fire is Rare Yellow (Summer) - Fire and Earth are Common, Water is Uncommon, and Wind is Rare Red (Fall) - Wind and Fire are Common, Earth is Uncommon, and Water is Rare Example: During Green (Spring), Earth and Water are the most common and will transmute into one crystal each, Wind is uncommon and will transmute into two crystals each, Fire is rare and will transmute into three crystals each. At the end of the game the points are calculated by adding the numbers on each played card and the crystal owned and substracting 5 points for each power card remaining in hand. The player with the most victory points wins. Note: Users need to discard energy immediately if the energy is more than the slots allocated. If a card allows you to summon another card but you have no space for this second card then it (the second card) will be discarded with no refund. == Difficulty levels: == '''Apprentice wizard level''' In order to make the game easier to learn, there are “pre-constructed” sets of nine power cards. Instead of taking step 1 of the first game phase, each player gets one of these sets. '''Magician level''' Only the power cards numbered 1 to 30 are in play. These cards have easy to grasp effects and will allow you to slowly discover the world of Seasons. '''Archmage level''' All 50 kinds of power cards are in play. The cards numbered 31 through 50 have more complex effects than the basic cards, but will allow you to extend the fun of playing by discovering new effects and combinations. 3119372c83c9eeeb0e1e725886df3bf740752487 Gamehelpcarrara 0 191 1481 2015-04-21T07:16:43Z Senatorhung 4176 Created page with "Link to english rules: https://dl.dropboxusercontent.com/u/720402/Palaces%20of%20Carrara.pdf" wikitext text/x-wiki Link to english rules: https://dl.dropboxusercontent.com/u/720402/Palaces%20of%20Carrara.pdf 2fe801ee6e64802ff2135d819fd0c527b46e9a46 Help 0 4 1482 1337 2015-04-27T13:57:30Z Sourisdudesert 1 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] is the most complete source of help for BGA. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcheckers|Checkers]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpeightmastersrevenge|8 Master's Revenge]] * [[Gamehelpelfenland|Elfenland]] </td> <td valign="top"> * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpinjawara|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] </td> <td valign="top"> * [[Gamehelpkoryo|Koryŏ]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsechsnimmt|6 Nimmt!]] </td> <td valign="top"> * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelpsechsnimmt|Take 5!]] * [[Gamehelptashkalar|Tash-Kalar]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] </td> <td valign="top"> * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> 0995ca56598fd11e793f09fc6ee1970b0d9a2dd0 1486 1482 2015-04-27T14:02:45Z Sourisdudesert 1 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] is the most complete source of help for BGA. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcheckers|Checkers]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpeightmastersrevenge|8 Master's Revenge]] * [[Gamehelpelfenland|Elfenland]] </td> <td valign="top"> * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpinjawara|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] </td> <td valign="top"> * [[Gamehelpkoryo|Koryŏ]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsechsnimmt|6 Nimmt!]] </td> <td valign="top"> * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelpsechsnimmt|Take 5!]] * [[Gamehelptashkalar|Tash-Kalar]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] </td> <td valign="top"> * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> 3e97aa2a3da3438e7b8372e376a562b9d0d04070 About Board Game Arena 0 5 1483 1246 2015-04-27T13:59:04Z Sourisdudesert 1 wikitext text/x-wiki With '''Board Game Arena''' you can play board games online with the whole world. Board Game Arena is a next generation game platform which makes online gaming more simple and attractive: * Nothing to install: play straight from your browser, from anywhere, at anytime. * Real time: your opponents are online, you play "live" (note: you can also choose to play "turn-based" games with opponents that are not online at the same time than you). * Simple: if you know the game, then you know how to play online. * Free. Board Game Arena offers a [http://en.boardgamearena.com/#!gamelist growing selection of board and card games]. We specialize in modern adults games ("European style games"). This game platform has been designed to host any kind of game. This flexibility allows us to offer a '''new game every month'''. 12a207314580b122d7fb0e1b425089f9f03842e8 Getting started 0 10 1484 918 2015-04-27T14:01:57Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] With '''Board Game Arena''' you can play within a few clicks. By choosing "[http://en.boardgamearena.com/#!lobby Play now]" on the left menu, you get a list of game tables waiting for players. You should select the games you want to play now to make them appear at the top of the page. You can join a game by clicking on a table, then click on "Join game". If you prefer, you can create a new game table: click on the green play button that corresponds to the game you want to play, and wait for your opponents. Important to know before you start: * It's much better to join a table already created than to create a new one. * For most popular games you will find opponents at any time. For the others, try to connect around peak hour (around 22h CEST) to maximize your chances. * When you start a game you can't leave the table until it ends. If you leave you will receive a penalty which will create difficulties finding opponents later. 24740fbc331aa195b8cf783295b9568e836f47e0 Referral 0 11 1485 551 2015-04-27T14:02:30Z Sourisdudesert 1 Replaced content with "[[Category:Help]] Note: this page has been deprecated." wikitext text/x-wiki [[Category:Help]] Note: this page has been deprecated. 5d2e9a0f874cd2a8b8e8e2ec2b041e66ee76b14a Game clock 0 15 1487 1375 2015-04-27T14:13:35Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] On '''Board Game Arena''' you are playing "live" (real time) or "turn-based" (asynchronously). In both cases, you have an allotted delay to play your moves. Most of the time, your initial delay at the beginning of a game is some minutes (in realtime mode) or some days (in turn-based mode). During each turn, or on specific occasions, you get an additional delay. If you have no more time to play, you will get a "clock" penalty and your opponents can decide to skip your turns (and consequently make you loose the game). == Game clock system philosophy == The game clock has been designed with the following principles: * Make sure that if your opponent left the game (or has been disconnected), it won't take long before you can expel him and win the game by forfeit. * Expelling an opponent is always a volunteer action, so you can agree with your opponent to forget the time limit if you want to. * If your opponent does not play and run out of time, this is always more interesting for you to try to make him back into the game than to punish him with penalties or skipping turn. In anyway, don't forget that respecting your allotted time is VERY important. == Time to think == Your allotted time to think is displayed on the right of your player's name. When it's your turn to play, this time is also displayed at the top of the web page. == Game speed == Table administrator can make a choice between some game speed profile (example: fast, normal, slow). There are many speeds for each mode (realtime and turn-based). The additional amount of time credited each turn depends on the chosen game speed profile. Be careful to check the game speed setting before the game starts to adjust your timing. The interface displays an estimation of the game duration based on recently played games with the same speed settings. Note: your allotted time to think cannot get higher that your initial time to think. For example, if you start the game with 5 minutes of thinking time, you time will be limited to 5 minutes maximum. Note: playing without a time limit is strongly discouraged, except if you are playing with friends, or to discover a new game. Remember that without time limit, you can't skip the turn of a player that is not playing. == Running out of time == As soon as you run out of time (negative clock), you get a clock penalty. When a player has a negative clock, any one of his opponents can make him skip his turn. Once this has been done, all following turns are skipped automatically. After player A's turn has been "skipped", the game results are "neutralized". It means that: * Player A is going to loose the game anyway. When you are in this situation (turns skipped automatically), you can get back in the game by clicking on the dedicated button "get back in this game". Note that you are not allowed to get back in the game if your clock is still negative. However, as all your turn are skipped, it shouldn't take long before your clock becomes positive again. If you can't/don't manage to get back in the game before the game end, you will get '''both''' a "leave" penalty on your profile and an ELO penalty for this game. '''For turn-based games''': On turn-based games, you are warned by email when you are running out of time. When you are out of time, your opponents also receive an email notifying them that they can make you skip your turn (they can also choose to wait if they don't mind or if you told them that you would be offline for some time). == Continue the game after a "skip turn" == If you are playing in a game where a player skips all his turns, you have 2 options: * You can continue to play the game until the end. This is recommended. In this case you will earn the ELO points you deserve for your victory. * You can abandon the game. All players with a negative clock will accept automatically and receive '''both''' an ELO penalty and a "leave" penalty. But the you and the other players with a positive clock won't get any ELO since the game didn't reach its end). == "My opponent is too slow" == Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his allotted time to think. If you want to play fast, set up or join only tables with "fast" mode on, but don't bully an opponent to play when he has the right to use his alloted time to think. == "I would like to think a little" == If you are in a critical step of the game and want to take some time to think, you can click on the "I would like to think a little" link at the top right of the page. Thus, your opponents will get a message and won't be thinking that you are away from keyboard or disconnected. Clicking on this link is not mandatory, but we encourage its use as a courtesy. 32a43c50fa0683349d3d34edeaa82040fe9e1c36 1488 1487 2015-04-27T14:23:00Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] On '''Board Game Arena''' you are playing "live" (real time) or "turn-based" (asynchronously). In both cases, you have an allotted delay to play your moves. Most of the time, your initial delay at the beginning of a game is some minutes (in realtime mode) or some days (in turn-based mode). During each turn, or on specific occasions, you get an additional delay. If you have no more time to play, you will get a "clock" penalty and your opponents can decide to skip your turns (and consequently make you loose the game). == Game clock system philosophy == The game clock has been designed with the following principles: * Even if you are in a loosing position, this is always more interesting (for your ELO and your reputation) to play the game until the end. * Make sure that if your opponent left the game (or has been disconnected), it won't take long before you can expel him and win the game by forfeit. * Expelling an opponent is always a volunteer action, so you can agree with your opponent to forget the time limit if you want to. * If your opponent does not play and run out of time, this is always more interesting for you to try to make him back into the game than to punish him with penalties or skipping turn. In anyway, don't forget that respecting your allotted time is VERY important. == Time to think == Your allotted time to think is displayed on the right of your player's name. When it's your turn to play, this time is also displayed at the top of the web page. == Game speed == Table administrator can make a choice between some game speed profile (example: fast, normal, slow). There are many speeds for each mode (realtime and turn-based). The additional amount of time credited each turn depends on the chosen game speed profile. Be careful to check the game speed setting before the game starts to adjust your timing. The interface displays an estimation of the game duration based on recently played games with the same speed settings. Note: your allotted time to think cannot get higher that your initial time to think. For example, if you start the game with 5 minutes of thinking time, you time will be limited to 5 minutes maximum. Note: playing without a time limit is strongly discouraged, except if you are playing with friends, or to discover a new game. Remember that without time limit, you can't skip the turn of a player that is not playing. == Running out of time == As soon as you run out of time (negative clock), you get a clock penalty. When a player has a negative clock, any one of his opponents can make him skip his turn. Once this has been done, all following turns are skipped automatically. After player A's turn has been "skipped" at y% of game progression, the game results are "neutralized". It means that: * Player A is going to loose the game anyway (last position), with the corresponding ELO loss. * In addition, Player A will get a "leave" penalty on his profile and an additional -10 ELO points penalty. * Player A's opponents are going to win the game anyway (all tied at the first position), with y% of the ELO points they would have normally won. Example: player "Albert" left a 2 players game at 50% of the game progression. His opponent "Ben" skips his turn. At the end of the game, "Albert" will get -30 ELO points (normal loss for a game loss) plus an additional -10 ELO points (penalty for leaving), plus a red "leave" penalty on his reputation profile. "Ben" is going to win 15 ELO points (50% of the normal 30 ELO points win). Note: you can't skip the turn of an opponent if your own clock is even more negative than him. For example, if "Ben"'s clock is -3:45 and "Albert"'s clock is "-0:05", Albert can expel Ben but Ben cannot expel Albert. == Continue the game after a "skip turn" == If you are playing in a game where a player skips all his turns, you may continue the game if you like, or not. This has no effect on anything (game results, penalties, and so on...). This is "just for fun". == "My opponent is too slow" == Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his allotted time to think. If you want to play fast, set up or join only tables with "fast" mode on, but don't bully an opponent to play when he has the right to use his alloted time to think. == "I would like to think a little" == If you are in a critical step of the game and want to take some time to think, you can click on the "I would like to think a little" link at the top right of the page. Thus, your opponents will get a message and won't be thinking that you are away from keyboard or disconnected. Clicking on this link is not mandatory, but we encourage its use as a courtesy. 3652daf755b4302fb26dd6b11b8582f851a8b29d 1497 1488 2015-04-28T11:42:03Z Kara thrace 2819 /* Running out of time */ wikitext text/x-wiki [[Category:Help]] On '''Board Game Arena''' you are playing "live" (real time) or "turn-based" (asynchronously). In both cases, you have an allotted delay to play your moves. Most of the time, your initial delay at the beginning of a game is some minutes (in realtime mode) or some days (in turn-based mode). During each turn, or on specific occasions, you get an additional delay. If you have no more time to play, you will get a "clock" penalty and your opponents can decide to skip your turns (and consequently make you loose the game). == Game clock system philosophy == The game clock has been designed with the following principles: * Even if you are in a loosing position, this is always more interesting (for your ELO and your reputation) to play the game until the end. * Make sure that if your opponent left the game (or has been disconnected), it won't take long before you can expel him and win the game by forfeit. * Expelling an opponent is always a volunteer action, so you can agree with your opponent to forget the time limit if you want to. * If your opponent does not play and run out of time, this is always more interesting for you to try to make him back into the game than to punish him with penalties or skipping turn. In anyway, don't forget that respecting your allotted time is VERY important. == Time to think == Your allotted time to think is displayed on the right of your player's name. When it's your turn to play, this time is also displayed at the top of the web page. == Game speed == Table administrator can make a choice between some game speed profile (example: fast, normal, slow). There are many speeds for each mode (realtime and turn-based). The additional amount of time credited each turn depends on the chosen game speed profile. Be careful to check the game speed setting before the game starts to adjust your timing. The interface displays an estimation of the game duration based on recently played games with the same speed settings. Note: your allotted time to think cannot get higher that your initial time to think. For example, if you start the game with 5 minutes of thinking time, you time will be limited to 5 minutes maximum. Note: playing without a time limit is strongly discouraged, except if you are playing with friends, or to discover a new game. Remember that without time limit, you can't skip the turn of a player that is not playing. == Running out of time == As soon as you run out of time (negative clock), you get a clock penalty. When a player has a negative clock, any one of his opponents can make him skip his turn. Once this has been done, all following turns are skipped automatically. After player A's turn has been "skipped" at y% of game progression, the game results are "neutralized". It means that: * Player A is going to loose the game anyway (last position), with the corresponding ELO loss. * In addition, Player A will get a "leave" penalty on his profile and an additional -10 ELO points penalty. * Player A's opponents are going to win the game anyway (all tied at the first position), with y% of the ELO points they would have normally won. This is impossible to lose points when your opponent left the game. Example: player "Albert" left a 2 players game at 50% of the game progression. His opponent "Ben" skips his turn. At the end of the game, "Albert" will get -30 ELO points (normal loss for a game loss) plus an additional -10 ELO points (penalty for leaving), plus a red "leave" penalty on his reputation profile. "Ben" is going to win 15 ELO points (50% of the normal 30 ELO points win). Note: you can't skip the turn of an opponent if your own clock is even more negative than him. For example, if "Ben"'s clock is -3:45 and "Albert"'s clock is "-0:05", Albert can expel Ben but Ben cannot expel Albert. == Continue the game after a "skip turn" == If you are playing in a game where a player skips all his turns, you may continue the game if you like, or not. This has no effect on anything (game results, penalties, and so on...). This is "just for fun". == "My opponent is too slow" == Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his allotted time to think. If you want to play fast, set up or join only tables with "fast" mode on, but don't bully an opponent to play when he has the right to use his alloted time to think. == "I would like to think a little" == If you are in a critical step of the game and want to take some time to think, you can click on the "I would like to think a little" link at the top right of the page. Thus, your opponents will get a message and won't be thinking that you are away from keyboard or disconnected. Clicking on this link is not mandatory, but we encourage its use as a courtesy. 057aa9b0e74c2ed9b6c0e3002451b62fc9de8c83 Faq 0 3 1502 1501 2015-04-28T12:13:45Z Sourisdudesert 1 /* Issues with BGA */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account "Most wanted games" list? When these games will be on BGA? === You should read the previous question ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refuses), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why some games has expansions on BGA and some hasn't? === You should read first the previous question ("how do we select games that are on BGA?"). Game expansion follows the same steps than games. There can be various reasons why a game publisher don't want the expansion online, and sometimes we don't find a developer that have the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licence" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes this is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. This is also possible to bring your own developer: of course it accelerates the process a lot! == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Bad performances === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 seconds. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this is the best approach for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allow us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 5fd0d77cee67bbd5448f259152b794bbb110f6db 1503 1502 2015-04-28T12:15:50Z Sourisdudesert 1 /* Issues with BGA */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account "Most wanted games" list? When these games will be on BGA? === You should read the previous question ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refuses), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why some games has expansions on BGA and some hasn't? === You should read first the previous question ("how do we select games that are on BGA?"). Game expansion follows the same steps than games. There can be various reasons why a game publisher don't want the expansion online, and sometimes we don't find a developer that have the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licence" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes this is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. This is also possible to bring your own developer: of course it accelerates the process a lot! == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why BGA is slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 seconds. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [Moderation and grades] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this is the best approach for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allow us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 90eb3eb58f394832617548082c91d2828dd8dc45 1504 1503 2015-04-28T12:16:18Z Sourisdudesert 1 /* I got issue with a specific player: how does the moderation works? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account "Most wanted games" list? When these games will be on BGA? === You should read the previous question ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refuses), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why some games has expansions on BGA and some hasn't? === You should read first the previous question ("how do we select games that are on BGA?"). Game expansion follows the same steps than games. There can be various reasons why a game publisher don't want the expansion online, and sometimes we don't find a developer that have the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licence" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes this is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. This is also possible to bring your own developer: of course it accelerates the process a lot! == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why BGA is slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 seconds. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this is the best approach for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allow us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 39c40426d870e8a0b207e756cec9411b9c819858 1508 1504 2015-04-28T12:25:00Z Sourisdudesert 1 /* Issues with BGA */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account "Most wanted games" list? When these games will be on BGA? === You should read the previous question ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refuses), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why some games has expansions on BGA and some hasn't? === You should read first the previous question ("how do we select games that are on BGA?"). Game expansion follows the same steps than games. There can be various reasons why a game publisher don't want the expansion online, and sometimes we don't find a developer that have the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licence" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes this is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. This is also possible to bring your own developer: of course it accelerates the process a lot! == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA do not support tablet/smartphones. There are tons of board gamers adaptations for tablet/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plan to do a mobile / tablet version at now. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why BGA is slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 seconds. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this is the best approach for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allow us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) db647a699b8d7dbc06224ad7a79c5ca8ca033291 1509 1508 2015-04-28T12:27:49Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account "Most wanted games" list? When these games will be on BGA? === You should read the previous question ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refuses), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why some games has expansions on BGA and some hasn't? === You should read first the previous question ("how do we select games that are on BGA?"). Game expansion follows the same steps than games. There can be various reasons why a game publisher don't want the expansion online, and sometimes we don't find a developer that have the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licence" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes this is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. This is also possible to bring your own developer: of course it accelerates the process a lot! == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA do not support tablet/smartphones. There are tons of board gamers adaptations for tablet/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plan to do a mobile / tablet version at now. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why BGA is slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 seconds. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this is the best approach for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allow us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 3b680a0d0207be49d4f94d665f3a3eae0d567ec9 1510 1509 2015-04-28T12:37:53Z Sourisdudesert 1 /* Issues with BGA */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account "Most wanted games" list? When these games will be on BGA? === You should read the previous question ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refuses), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why some games has expansions on BGA and some hasn't? === You should read first the previous question ("how do we select games that are on BGA?"). Game expansion follows the same steps than games. There can be various reasons why a game publisher don't want the expansion online, and sometimes we don't find a developer that have the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licence" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes this is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. This is also possible to bring your own developer: of course it accelerates the process a lot! == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is chance that we fix 3 or 4 minor bug at the same time. BGA is known for the quality of its adaptation, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so much critical bugs with many "green thumb". Please also note that BGA adaptations are realized by volunteers and not professional developers (even if most of them are also professional developers). This is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA do not support tablet/smartphones. There are tons of board gamers adaptations for tablet/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plan to do a mobile / tablet version at now. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why BGA is slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 seconds. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this is the best approach for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allow us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) dc40238b27534cff6e45627438154eee0902bbc8 1511 1510 2015-04-28T12:39:40Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the right owner (most of the time: original publisher of the game). * A software developer that develop the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorization, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptions on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). In the other hand, we got some authorizations for some very good games but no developers volunteers to develop it, or sometimes some of them didn't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronized the release of a game with a publisher event, so the game adaptation can stay "hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't found a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already get the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account "Most wanted games" list? When these games will be on BGA? === You should read the previous question ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refuses), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why some games has expansions on BGA and some hasn't? === You should read first the previous question ("how do we select games that are on BGA?"). Game expansion follows the same steps than games. There can be various reasons why a game publisher don't want the expansion online, and sometimes we don't find a developer that have the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the boardgame community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licence" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes this is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. This is also possible to bring your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is chance that we fix 3 or 4 minor bug at the same time. BGA is known for the quality of its adaptation, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so much critical bugs with many "green thumb". Please also note that BGA adaptations are realized by volunteers and not professional developers (even if most of them are also professional developers). This is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA do not support tablet/smartphones. There are tons of board gamers adaptations for tablet/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plan to do a mobile / tablet version at now. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why BGA is slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 seconds. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this is the best approach for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allow us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) ad3afa648b682fa9d500e909f2b3afe3509341f0 1515 1511 2015-04-28T20:40:01Z Een 3 /* About board games we proposed on BGA */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is chance that we fix 3 or 4 minor bug at the same time. BGA is known for the quality of its adaptation, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so much critical bugs with many "green thumb". Please also note that BGA adaptations are realized by volunteers and not professional developers (even if most of them are also professional developers). This is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA do not support tablet/smartphones. There are tons of board gamers adaptations for tablet/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plan to do a mobile / tablet version at now. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why BGA is slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 seconds. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this is the best approach for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allow us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 391f9b8290ef550545e3a06d6ae1d8cae37d1adb 1516 1515 2015-04-28T20:41:49Z Een 3 /* How you guys make money? Do you make a living of it? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is chance that we fix 3 or 4 minor bug at the same time. BGA is known for the quality of its adaptation, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so much critical bugs with many "green thumb". Please also note that BGA adaptations are realized by volunteers and not professional developers (even if most of them are also professional developers). This is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA do not support tablet/smartphones. There are tons of board gamers adaptations for tablet/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plan to do a mobile / tablet version at now. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why BGA is slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 seconds. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) d097d8425b84330df2ed4902bcbb3b284a94531a 1517 1516 2015-04-28T20:46:56Z Een 3 /* Issues with BGA */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) dd7dcb1dbafe0bdf72864b428472fcd3b7d7df72 Moderation and grades 0 14 1505 35 2015-04-28T12:20:12Z Sourisdudesert 1 wikitext text/x-wiki [[Category:Help]] Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a '''mortal'''. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the '''angel''' grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to '''devilkin''' or '''demon'''. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. == Moderation == Moderation on BGA is community based. A group of volunteers process the reports, and decide which action to do (ex: exclude player for X days). BGA Moderators made a difficult work that is absolutely needed to have a nice community. You can see who they are from the [[http://boardgamearena.com/#!team BGA team]] page. Usually reports are processed quite fast, but sometimes this is not easy and there are some additional checks to perform. But we processed every report. == All grades == * '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraph can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherub check that Seraph are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...) * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. 6a5da75b55b6f71091b4e4417c9ca9be951c5b4c 1506 1505 2015-04-28T12:20:31Z Sourisdudesert 1 /* Moderation */ wikitext text/x-wiki [[Category:Help]] Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a '''mortal'''. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the '''angel''' grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to '''devilkin''' or '''demon'''. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. == Moderation == Moderation on BGA is community based. A group of volunteers process the reports, and decide which action to do (ex: exclude player for X days). BGA Moderators made a difficult work that is absolutely needed to have a nice community. You can see who they are from the [[http://boardgamearena.com/#!team BGA team]] page. Usually reports are processed quite fast, but sometimes this is not easy and there are some additional checks to perform. But don't be afraid: we processed every report. == All grades == * '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraph can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherub check that Seraph are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...) * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. dac316d9f9210d20ace98c40f06c5d82a70ed8eb 1507 1506 2015-04-28T12:20:43Z Sourisdudesert 1 /* Moderation */ wikitext text/x-wiki [[Category:Help]] Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a '''mortal'''. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the '''angel''' grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to '''devilkin''' or '''demon'''. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. == Moderation == Moderation on BGA is community based. A group of volunteers process the reports, and decide which action to do (ex: exclude player for X days). BGA Moderators made a difficult work that is absolutely needed to have a nice community. You can see who they are from the [[http://boardgamearena.com/#!team BGA team]] page. Usually reports are processed quite fast, but sometimes this is not easy and there are some additional checks to perform. But don't be afraid: we review every report. == All grades == * '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraph can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherub check that Seraph are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...) * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. 0d5412d55d8a2993d53fb360242ffe5791216e6c Turn based FAQ 0 192 1512 2015-04-28T12:53:18Z Sourisdudesert 1 Created page with " == What is turn-based mode? == === What is turn-based mode? === When playing on BGA in real-time, you and your opponents are online at the same time. Playing turn-based, y..." wikitext text/x-wiki == What is turn-based mode? == === What is turn-based mode? === When playing on BGA in real-time, you and your opponents are online at the same time. Playing turn-based, you and your opponents don't need to be online at the same time. You play your move, your opponent gets an "it's your turn" message, and then he can play his turn as soon as possible. === Is turn-based better than real-time? === There is no "better" mode: the two modes are different and complementary. Real-time is good because games are fast, interaction between players is rich, and players are focused on the game. Turn-based is good because you can play whenever you want during your day, thinking as much as you want, with no time constraint. === Will real-time disappear from BGA? === Of course not. BGA main purpose is to provide real-time play. Turn-based is just an additional possibility offered to those who prefer to play this way. If you don't like playing turn-based, you have the possibility to switch off turn-based mode in the lobby, and then you will only see realtime tables: === How can I choose between realtime and turn-based? === Using a simple switch in the lobby, you are able to display real-time tables only, or turn-based tables only. == Why turn-based? == === A lot of websites already propose turn-based, so why are you? === At first, because we think that we can provide the best turn-based mode available for online boardgaming. We have our own vision of what "turn-based" is and how it should be done. Then, because we think that some games on BGA deserve the possibility to be played turn-based. Some games, especially those with a duration over a certain limit, don't have many players even though they are wonderful games. As we'd like to introduce longer & more complex games on BGA, we need a playing mode more suited to them. We also think it's bringing more players on BGA. If you have been playing on BGA for a long time, you're not very impressed by the website, but we know that real-time play is something intimidating for beginners. Playing turn based, they are able to learn the game and the interfaces slowly, and maybe later play these games in real-time. And finally, we are doing this... because we are geeks, and a geek is unable not to do something he can do :) === Why would I want to play turn-based? === Think about one of the following situations: * you are at work, and you have something like "5 minutes of Internet break every hour". There is no way you can play a real-time game on BGA, but you can play 4-5 turn-based games in parallel :) * you would like to try this new game on BGA but it looks complex, and you don't want to make an opponent wait while you learn how to play. Playing turn-based, you can take all needed time to familiarized yourself with the interface before playing. * instead of playing some "candy crush" game on your smartphone, you'd prefer to play on BGA. But in realtime this is really impossible with an unstable connexion. Besides you lose too much time scrolling. But playing turn based, it doesn't matter if the connection goes and comes, and you can take all the time you need on your little screen to play. * what about having a "turn based" breakfast on the morning? 4-5 tables are waiting for you, you are not stressed by the clock, you can think and play a complex game day after day :) === It takes weeks to finish a turn-based game, this is so boring === Yes and no. At first, it doesn't necessarily take weeks. Most games can be played in 2-3 days if opponents have regular time-slots to play during their day. But yes, some games can take weeks, but it doesn't mean they are not intense and compelling: players have time to think about their moves and can build strong strategies. So there are different "turn-based" flavors, from the very fast "10 moves/day" to the very slow "1 move/day". This is why we kept the "Game speed" BGA option for turn-based: you can specify the average number of moves per day, and BGA adapts the time limits to this average. This way you can have "fast turn based" or "slow turn based" depending on your taste (and your time). === A lot of turn-based games never come to an end... === This is true, but it's also true for real-time. Board Game Arena has a very efficient system to discourage players to leave the games (more than 98% of the games comes to a normal end). This system works also for turn-based, so we kept it. And we have 98% of games coming to a normal end :) == How does turn-based work on BGA? == === Which of the games are available in turn-based mode? Are some games available only in real-time/turn-based? === All games on BGA are available both in real-time AND turn-based mode. Of course for some games, warning messages and suggestions are displayed to incite you to prefer one mode over another. However, you are free to choose your preferred mode. Note: for technical reasons, some games can be unavailable for some mode, for some times. === How do I know if a table is realtime or turn-based? === Available real-time tables are displayed with a green background. Turn-based tables are displayed with a brown background. Turn-based / realtime is also specified in table description. === How do I start a turn-based game? === Using a simple switch in the lobby, you are able to display real-time tables only, or turn-based tables only. When you start a new table from the "turn-based" lobby, your table is created "turn-based". In fact, Turn-based is proposed as additional "Game speed" options: in addition to the classic "Slow speed / Normal speed / Fast speed" options, you now have "Turn based: 1 move / day", "Turn based: 2 moves / day", and so on. (note that there will be faster options than "2 moves/day" in the future). === Is it possible to play several games at the same time? === Yes. Of course we don't allow players to play several real-time games in parallel. For turn-based it's different: you are encouraged to play several games at the same time, with different opponents. This way, you don't have to wait a long time before an opponent gets online and plays a move. === Is it possible to play a real-time game if I'm also playing at some turn-based table? === Yes. === Is there a limit to the number of games I can play at the same time? === Yes and no. In the beginning, the number of parallel games will be limited to a small number in order we can start slowly and test together this new mode. Then, this limit will increase progressively, and we hope to remove it completely. === What happens if someone does not play for a long time? === The "time to think" system is the same than in realtime: _ you have a global thinking time for the game. _ you can be expelled from the game if you go over one or the other. The allotted times depends on the game speed option. === If I'm online at the same time than my opponent, can we play real-time? === Absolutely. When you opponent is online, the game works exactly like with a real-time game (no need to refresh the page, real-time chat, and so on). === Is it possible to communicate with other players in turn-based mode? === Yes. The chat works exactly like in real-time, except that your opponent will see your message the next time he/she will connect to the game. === Can I start a game in real-time and finish it turn-based, and the opposite?=== Yes and no. You can launch a turn-based game, then discuss with your opponent(s) to find a suitable time slot to play it real-time. But it will remain a turn-based table with turn-based time constraints. However, we hope to introduce these possibilities in the future. === Can I pause a game for a certain duration if all players agree? === This could be an interesting possibility offered by this new mode (for both realtime and turn-based) but it is not implemented at now. === How do I know if it's my turn when I'm not connected to BGA? === We provide you many different ways to do it. For now: _ you can receive an email each time this is your turn at a table. _ you can receive an email when it's your turn on any table, then don't receive any email until you connect and play a move on any table. _ you can receive a daily report with the tables waiting for you. All these options can be set from your Preferences page (Turn-based section). In the future, more channels will be opened in order to be notified efficiently when it's your turn. === How can I remember what previously happened in a game? === You can replay any part of the game by clicking on a message in the game log ("Replay from this point" functionality). === When does a turn-based game start?=== A turn based game starts as soon as the maximum number of players has been reached OR if the minimum number of players has been reached and the table admin decides to "start the game". === Is it possible to undo or reset a move? === This is a good question, but the answer is not obvious. The policy of BGA until turn-based was the following: no undo, except in specific situation where undo is possible and where this is not annoying for other players. For turn-based, the situation is quite different : if a player does an "undo", the other players doesn't care since they are not online at the same moment. So when it is possible and not annoying for the current player we may add an undo function. However it needs some extra, specific work on each game to have this. === I don't want to play with less than (or more than) X players. How to ensure this? === Table administrator can setup a minimum/maximum number of players, and these numbers cannot be changed after at least 1 opponent joined the game. If you don't want to play with less than X players (or more than X players), please make sure not to join games configured with a minimum number of player lower than X (or a maximum number of players greater than X). === After the turn-based game has started is there any possibility to see what the gamespeed is, how many turns per day? ==== Like any other options, you can check it while the game is running at the bottom of the page (or by a click on the gear wheel icon on the top right). 31ff86ec07e00121de5d931f455dc4fe88242e72 Reputation 0 17 1513 1132 2015-04-28T17:38:31Z Besen01 8761 translation wikitext text/x-wiki [[Category:Help]] == Was ist Reputation ? == Auf '''Board Game Arena''' möchten wir gerne eine überzeugende konkurrenzfähige Atmosphäre mit einer respektvollen und fairen Spielumgebung haben. Um diese Ziele zu erreichen, hat jeder Spieler ein '''Reputations-Profil", welches die Repräsentation seines generellen Verhaltens gegenüber anderen Spielern ist. Das Profil setzt sich aus folgenden 3 Eigenschaften zusammen: To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items: * Meinungen der anderen Spieler (http://fr.boardgamearena.com/theme/img/common/reputation_up.png und http://fr.boardgamearena.com/theme/img/common/reputation_down.png) * % der beendeten Spiele * % der ohne Zeitstrafe beendeten Spiele Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits. == How to increase my reputation / what makes my reputation decrease ? == At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks. * a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player. * a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player. You can only give a single thumb (green or red) to a single player. If your opinion changes you can click again on a thumb to reflect this change. As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended you leave the game or expel this player. By nature, opinions are subjective. There is nothing we can do for you if you receive a "red thumb" for an unfair reason. However, we know by experience that this system has a lot of advantages and generally gives relevant and useful information. Qn: its unclear if the "> 10% unfavorable" warning is calculated against the number of "thumbs up / thumbs down".. or "total number of unique players played with / thumbs down". Hope the formula is the latter.. as the first formula will raise many more warnings.. more idiots give thumbs down, and are lazier to give thumb up. == Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png == * Be polite! Say at least "hello" and "good luck" at the beginning of the game, and maybe "good game" ("gg") at the end of the game. * When you need some time to think, click on "I would like to think a little" link. * Always stay calm: it's a game. * Don't press your opponent to play if he has some time left. * If you really can't finish the game (this is not supposed to happen...), then say you are sorry and leave the game (don't wait to get expelled) to save your opponents time. Voluntarily disconnecting and conceding victory to the opponent does not cost you reputation like being expelled does. * Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!). * Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation. == What are the consequences of a bad reputation ? == A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you. It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents. b460804f15312094e9a13b166c7e6e492f22400c 1514 1513 2015-04-28T17:43:22Z Besen01 8761 /* Was ist Reputation ? */ wikitext text/x-wiki [[Category:Help]] == What is reputation ? == On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance. To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items: * Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png) * % of games you finished * % of games you finished with no clock penalties Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits. == How to increase my reputation / what makes my reputation decrease ? == At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks. * a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player. * a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player. You can only give a single thumb (green or red) to a single player. If your opinion changes you can click again on a thumb to reflect this change. As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended you leave the game or expel this player. By nature, opinions are subjective. There is nothing we can do for you if you receive a "red thumb" for an unfair reason. However, we know by experience that this system has a lot of advantages and generally gives relevant and useful information. Qn: its unclear if the "> 10% unfavorable" warning is calculated against the number of "thumbs up / thumbs down".. or "total number of unique players played with / thumbs down". Hope the formula is the latter.. as the first formula will raise many more warnings.. more idiots give thumbs down, and are lazier to give thumb up. == Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png == * Be polite! Say at least "hello" and "good luck" at the beginning of the game, and maybe "good game" ("gg") at the end of the game. * When you need some time to think, click on "I would like to think a little" link. * Always stay calm: it's a game. * Don't press your opponent to play if he has some time left. * If you really can't finish the game (this is not supposed to happen...), then say you are sorry and leave the game (don't wait to get expelled) to save your opponents time. Voluntarily disconnecting and conceding victory to the opponent does not cost you reputation like being expelled does. * Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!). * Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation. == What are the consequences of a bad reputation ? == A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you. It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents. 49a2e7d331367f58c6d40a603cadbbc69cc94a24 Gamehelpkahuna 0 193 1518 2015-05-02T11:05:48Z Mastercactaur 8790 Created page with "'''Summary:''' Players use cards to place bridges between islands or remove opponent's bridges. If you get the majority of bridges around an island, you place one of your mark..." wikitext text/x-wiki '''Summary:''' Players use cards to place bridges between islands or remove opponent's bridges. If you get the majority of bridges around an island, you place one of your marker stones on it and also remove any of your opponent's bridges to that island – which might cause them to lose a bridge majority on an adjacent island and lose a marker stone there. The game is played in three rounds. A round ends when all cards from the face down deck and the three face up cards have been taken. Then points are scored for the player with the most marker stones on the board. The game can also end sooner when one player has absolutely NO bridges left on the board. '''Playing the game:''' During a turn a player may play from 0-5 island cards. After playing all the island cards desired, the player draws one card to add to his hand. A player may never have more than 5 cards in his hand. Playing island cards • When a player plays a single card, he discards it and then places a bridge on one of the available dotted connecting lines between the island on the card and one of its neighbors. • If the player wants to play several cards, they are played and bridges placed one at a time. (exception: removal of opponent’s bridge) • Instead of playing card(s), a player may discard one or more cards secretly under the discard pile. • A player may choose to play no cards in a turn. Control of an island: marker stone placement • When a player has bridges on more than half of the connecting lines from an island, he controls that island and places one of his marker stones on the island. Note: the cards indicate the number of connecting lines an island has under its name. • When a player gains control of an island, he removes any bridges on that island belonging to his opponent. If such a removal causes the loss of control on a neighboring island, the marker stone on the effected island is also removed. Removal of opponent’s bridge A player may play a pair of island cards to remove an opponent’s bridge between two islands. The two cards must name only the two islands connected by the bridge to be removed. For example, the bridge connecting HUNA and ELAI can be removed only by playing one of the three following pairs of cards: "HUNA - ELAI ", "HUNA - HUNA " or "ELAI - ELAI ". The player could then play a card from either island (for example: HUNA or ELAI) to place his bridge between the two islands. Drawing an island card After a player has played all cards he desires, he may add one card to his hand, taking either one of the three face-up cards or the top card from the face-down stack. When one of the three face-up cards is taken, it is replaced by the top card from the face-down stack. However, if a player chooses not to take a card, his opponent must take a card on his next turn. If a player has five cards in his hand and chooses to take a card, he must first discard one or more cards. A player’s turn ends when he takes a card or indicates he has chosen not to take a card. '''Scoring, Rounds 1 & 2:''' When the last card is taken (from the face-down stack and the three face-up cards) in the first and second rounds, the number of marker stones each player has on the board are tallied. ''If the players control the same number of islands at the end of a round, no points are scored.'' After the ''first round'', the player with the most islands scores ''1 point''. After the ''second round'', the player with the most islands scores ''2 points''. After scoring, the discard pile is shuffled and three cards are placed face-up. Play continues with the player who was next to play when the last card was taken. '''Final Scoring and Game End:''' When the last card from the face-down deck is taken at the end of the third round and the last of the face up cards has been taken, each player takes one additional turn (without taking cards). After those two turns, the islands are scored for the third and final time. This time the player with the most islands is awarded the difference in points. These points are added to those previously earned. The player with the most total points from the three rounds is the winner. If there is a tie, the player who scored most in the third round is the winner. If there is still a tie, the player with the most bridges at the end is the winner. The game can also be ended at any time during the second or third round if one player has no bridges on the board. If this happens, the other player is the winner. 9a2b8ca2eb4b2779d1b9008ebb47c89f28b005fe 1519 1518 2015-05-02T11:13:09Z Mastercactaur 8790 wikitext text/x-wiki == Summary: == Players use cards to place bridges between islands or remove opponent's bridges. If you get the majority of bridges around an island, you place one of your marker stones on it and also remove any of your opponent's bridges to that island – which might cause them to lose a bridge majority on an adjacent island and lose a marker stone there. The game is played in three rounds. A round ends when all cards from the face down deck and the three face up cards have been taken. Then points are scored for the player with the most marker stones on the board. The game can also end sooner when one player has absolutely NO bridges left on the board. == Playing the game: == During a turn a player may play from 0-5 island cards. After playing all the island cards desired, the player draws one card to add to his hand. A player may never have more than 5 cards in his hand. '''Playing island cards''' • When a player plays a single card, he discards it and then places a bridge on one of the available dotted connecting lines between the island on the card and one of its neighbors. • If the player wants to play several cards, they are played and bridges placed one at a time. (exception: removal of opponent’s bridge) • Instead of playing card(s), a player may discard one or more cards secretly under the discard pile. • A player may choose to play no cards in a turn. '''Control of an island: marker stone placement''' • When a player has bridges on more than half of the connecting lines from an island, he controls that island and places one of his marker stones on the island. Note: the cards indicate the number of connecting lines an island has under its name. • When a player gains control of an island, he removes any bridges on that island belonging to his opponent. If such a removal causes the loss of control on a neighboring island, the marker stone on the effected island is also removed. '''Removal of opponent’s bridge''' A player may play a pair of island cards to remove an opponent’s bridge between two islands. The two cards must name only the two islands connected by the bridge to be removed. For example, the bridge connecting HUNA and ELAI can be removed only by playing one of the three following pairs of cards: "HUNA - ELAI ", "HUNA - HUNA " or "ELAI - ELAI ". The player could then play a card from either island (for example: HUNA or ELAI) to place his bridge between the two islands. '''Drawing an island card''' After a player has played all cards he desires, he may add one card to his hand, taking either one of the three face-up cards or the top card from the face-down stack. When one of the three face-up cards is taken, it is replaced by the top card from the face-down stack. However, if a player chooses not to take a card, his opponent must take a card on his next turn. If a player has five cards in his hand and chooses to take a card, he must first discard one or more cards. A player’s turn ends when he takes a card or indicates he has chosen not to take a card. == Scoring, Rounds 1 & 2: == When the last card is taken (from the face-down stack and the three face-up cards) in the first and second rounds, the number of marker stones each player has on the board are tallied. '''''If the players control the same number of islands at the end of a round, no points are scored.''''' After the '''''first round''''', the player with the most islands scores '''''1 point'''''. After the '''''second round''''', the player with the most islands scores '''''2 points'''''. After scoring, the discard pile is shuffled and three cards are placed face-up. Play continues with the player who was next to play when the last card was taken. == Final Scoring and Game End: == When the last card from the face-down deck is taken at the end of the third round and the last of the face up cards has been taken, each player takes one additional turn (without taking cards). After those two turns, the islands are scored for the third and final time. This time the player with the most islands is awarded the difference in points. These points are added to those previously earned. The player with the most total points from the three rounds is the winner. If there is a tie, the player who scored most in the third round is the winner. If there is still a tie, the player with the most bridges at the end is the winner. The game can also be ended at any time during the second or third round if one player has no bridges on the board. If this happens, the other player is the winner. d3b9f481a65bb7dc379c06adb2ba4894723ad3cc 1520 1519 2015-05-02T11:13:45Z Mastercactaur 8790 wikitext text/x-wiki == Summary: == Players use cards to place bridges between islands or remove opponent's bridges. If you get the majority of bridges around an island, you place one of your marker stones on it and also remove any of your opponent's bridges to that island – which might cause them to lose a bridge majority on an adjacent island and lose a marker stone there. The game is played in three rounds. A round ends when all cards from the face down deck and the three face up cards have been taken. Then points are scored for the player with the most marker stones on the board. The game can also end sooner when one player has absolutely NO bridges left on the board. == Playing the game: == During a turn a player may play from 0-5 island cards. After playing all the island cards desired, the player draws one card to add to his hand. A player may never have more than 5 cards in his hand. '''Playing island cards''' • When a player plays a single card, he discards it and then places a bridge on one of the available dotted connecting lines between the island on the card and one of its neighbors. • If the player wants to play several cards, they are played and bridges placed one at a time. (exception: removal of opponent’s bridge) • Instead of playing card(s), a player may discard one or more cards secretly under the discard pile. • A player may choose to play no cards in a turn. '''Control of an island: marker stone placement''' • When a player has bridges on more than half of the connecting lines from an island, he controls that island and places one of his marker stones on the island. Note: the cards indicate the number of connecting lines an island has under its name. • When a player gains control of an island, he removes any bridges on that island belonging to his opponent. If such a removal causes the loss of control on a neighboring island, the marker stone on the effected island is also removed. '''Removal of opponent’s bridge''' A player may play a pair of island cards to remove an opponent’s bridge between two islands. The two cards must name only the two islands connected by the bridge to be removed. For example, the bridge connecting HUNA and ELAI can be removed only by playing one of the three following pairs of cards: "HUNA - ELAI", "HUNA - HUNA", or "ELAI - ELAI". The player could then play a card from either island (for example: HUNA or ELAI) to place his bridge between the two islands. '''Drawing an island card''' After a player has played all cards he desires, he may add one card to his hand, taking either one of the three face-up cards or the top card from the face-down stack. When one of the three face-up cards is taken, it is replaced by the top card from the face-down stack. However, if a player chooses not to take a card, his opponent must take a card on his next turn. If a player has five cards in his hand and chooses to take a card, he must first discard one or more cards. A player’s turn ends when he takes a card or indicates he has chosen not to take a card. == Scoring, Rounds 1 & 2: == When the last card is taken (from the face-down stack and the three face-up cards) in the first and second rounds, the number of marker stones each player has on the board are tallied. '''''If the players control the same number of islands at the end of a round, no points are scored.''''' After the '''''first round''''', the player with the most islands scores '''''1 point'''''. After the '''''second round''''', the player with the most islands scores '''''2 points'''''. After scoring, the discard pile is shuffled and three cards are placed face-up. Play continues with the player who was next to play when the last card was taken. == Final Scoring and Game End: == When the last card from the face-down deck is taken at the end of the third round and the last of the face up cards has been taken, each player takes one additional turn (without taking cards). After those two turns, the islands are scored for the third and final time. This time the player with the most islands is awarded the difference in points. These points are added to those previously earned. The player with the most total points from the three rounds is the winner. If there is a tie, the player who scored most in the third round is the winner. If there is still a tie, the player with the most bridges at the end is the winner. The game can also be ended at any time during the second or third round if one player has no bridges on the board. If this happens, the other player is the winner. 9c0dd8984acf3a4ea5b6faeeacf6eda5020a84e5 Gamehelpnorthwestpassage 0 121 1521 873 2015-05-04T20:09:51Z Savama 7567 wikitext text/x-wiki '''''North-West Passage''''' ''In 1845, Sir John Franklin led an expedition on behalf of the British Royal Navy to find and explore the last portion of the Northwest Passage. They sailed into unknown waters, and no-one ever heard from them again... Players must venture into these hazardous Arctic waters in order to discover Franklin’s fate and succeed where he failed: by finding the Northwest Passage.'' ---- In the game, prestige is awarded for exploring islands and straits, getting information from Inuits or Cairns about the Franklin Expedition, finding shipwrecks of the expedition, and for being among the first to find their way up to the Northwest Passage and back to Groenland. The player with the most Prestige points at the end of the game is the winner. In case of a tie, the first tied player to have returned to Greenland is the winner. == GAME CYCLE == The game is divided into ten rounds. At the end of each round, the solar disc moves, and part of the board above the sun freezes into ice or melts back to sea. During one round, player will take up to 7 actions, in turn. Actions can be taken either from the ship, using crewmen on the ship, or from the sled, using crewmen on the sled. During one turn, one player can play one or more actions. However, '''all additional actions (beyond the first one) will cost one more crewman than normal'''. In order to stop playing more actions during one turn, click the blinking [End Turn] at the top of the screen. At the end of the round, all used Crewmen move back to «Available». The next turn order is the order in which players used their last crewmen (or passed). This is shown by the turn order markers at the top left of the board. == ACTIONS == === Draw a tile === ''Cost: 1 Crewman'' <Click on the chosen tile at the top of the board.> <br/> === Refresh tiles and Draw === ''Cost: 2 Crewmen'' <Click on the "Renew deck" icon.> The player MUST: # Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve. # Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve. <br/> === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. 64d05e47481051539ff086795875148ba9a5600f 1522 1521 2015-05-04T20:10:25Z Savama 7567 wikitext text/x-wiki == '''North-West Passage''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. In the game, prestige is awarded for exploring islands and straits, getting information from Inuits or Cairns about the Franklin Expedition, finding shipwrecks of the expedition, and for being among the first to find their way up to the Northwest Passage and back to Groenland. The player with the most Prestige points at the end of the game is the winner. In case of a tie, the first tied player to have returned to Greenland is the winner. == GAME CYCLE == The game is divided into ten rounds. At the end of each round, the solar disc moves, and part of the board above the sun freezes into ice or melts back to sea. During one round, player will take up to 7 actions, in turn. Actions can be taken either from the ship, using crewmen on the ship, or from the sled, using crewmen on the sled. During one turn, one player can play one or more actions. However, '''all additional actions (beyond the first one) will cost one more crewman than normal'''. In order to stop playing more actions during one turn, click the blinking [End Turn] at the top of the screen. At the end of the round, all used Crewmen move back to «Available». The next turn order is the order in which players used their last crewmen (or passed). This is shown by the turn order markers at the top left of the board. == ACTIONS == === Draw a tile === ''Cost: 1 Crewman'' <Click on the chosen tile at the top of the board.> <br/> === Refresh tiles and Draw === ''Cost: 2 Crewmen'' <Click on the "Renew deck" icon.> The player MUST: # Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve. # Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve. <br/> === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. 2d935667536ab7d82ba3075d9ffc3f6fab8c0c2b 1523 1522 2015-05-04T20:11:13Z Savama 7567 wikitext text/x-wiki == '''Північно-Західна Протока [Expedition Northwest Passage]''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. == '''Мета гри''' == Гравець, що здобуває найбільше очок Престижу перемагає. У разі нічиєї, перемагає гравець, що перший повернувся до Гренландії. == GAME CYCLE == The game is divided into ten rounds. At the end of each round, the solar disc moves, and part of the board above the sun freezes into ice or melts back to sea. During one round, player will take up to 7 actions, in turn. Actions can be taken either from the ship, using crewmen on the ship, or from the sled, using crewmen on the sled. During one turn, one player can play one or more actions. However, '''all additional actions (beyond the first one) will cost one more crewman than normal'''. In order to stop playing more actions during one turn, click the blinking [End Turn] at the top of the screen. At the end of the round, all used Crewmen move back to «Available». The next turn order is the order in which players used their last crewmen (or passed). This is shown by the turn order markers at the top left of the board. == ACTIONS == === Draw a tile === ''Cost: 1 Crewman'' <Click on the chosen tile at the top of the board.> <br/> === Refresh tiles and Draw === ''Cost: 2 Crewmen'' <Click on the "Renew deck" icon.> The player MUST: # Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve. # Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve. <br/> === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. 7f63cbdd95e6ea2f1f8df5ea767fd6c3f16e4b78 1524 1523 2015-05-04T20:12:03Z Savama 7567 wikitext text/x-wiki == '''Північно-Західна Протока [Expedition Northwest Passage]''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. == '''Мета гри''' == Гравець, що здобуває найбільше очок Престижу перемагає. У разі нічиєї, перемагає гравець, що перший повернувся до Гренландії. == '''Опис гри''' == На початку гри кожен гравець отримує: особисте гральне поле, корабель (розміщується на стрілці Гренландія), сани (розміщуються на особистому гральному полі), 7 моряків. Гра триває 10 раундів. Кожен раунд складається з двох фаз: 1) ''Фаза дій'', коли гравці виконують доступні дії; 2) ''Фаза завершення раунду'', коли пересувається Диск сонця й відбувається підготовка до наступного раунду. == ACTIONS == === Draw a tile === ''Cost: 1 Crewman'' <Click on the chosen tile at the top of the board.> <br/> === Refresh tiles and Draw === ''Cost: 2 Crewmen'' <Click on the "Renew deck" icon.> The player MUST: # Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve. # Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve. <br/> === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. 5b6bd3b69b389281e7e9306ce08000a5ba6ba386 1525 1524 2015-05-04T20:13:28Z Savama 7567 wikitext text/x-wiki == '''Північно-Західна Протока [Expedition Northwest Passage]''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. == '''Мета гри''' == Гравець, що здобуває найбільше очок Престижу перемагає. У разі нічиєї, перемагає гравець, що перший повернувся до Гренландії. == '''Опис гри''' == На початку гри кожен гравець отримує: особисте гральне поле, корабель (розміщується на стрілці Гренландія), сани (розміщуються на особистому гральному полі), 7 моряків. Гра триває 10 раундів. Кожен раунд складається з двох фаз: 1) ''Фаза дій'', коли гравці виконують доступні дії; 2) ''Фаза завершення раунду'', коли пересувається Диск Cонця й відбувається підготовка до наступного раунду. == '''Фаза дій''' == Гравець має 7 моряків, що їх можна використати для виконання таких дій: 1) Взяти плитку; 2) Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них; 3) Викласти плитку на гральну дошку; 4) Перевести моряків (з корабля на сани і навпаки); 5) Пересунути корабель або сани; 6) Дослідити; 7) Знайти; 8) Спасувати. На особистому гральному полі гравця є дві зони – "Корабель" та "Сани", що своєю чергою діляться на дві частини "Готові" та "Відпочивальники". Корабель чи Сани можуть виконувати будь-які дії, коли на них є матроси. На початку гри всі моряки перебувають на кораблі. Щойно гравець переводить їх на сани, як здобуває можливість пересувати їх по гральній дошці. Щоб виконати завдання гравець має використати потрібну кількість моряків. Щоб зазначити дію, гравець переміщає потрібну кількість моряків з "Готових" до "Відпочивальників" на кораблі чи на санах. Гравці виконують дії почергово, аж поки всі не спасують. Протягом ходу гравець: - МУСИТЬ виконати одну дію, використовуючи для цього потрібну кількість моряків. Якщо гравець не має "Готових" моряків, то він може лише спасувати. - Після виконання першої дії гравець може виконати одну або більше додаткових дій. Додаткові дії потребують участі на одного моряка більше, ніж зазвичай. == ACTIONS == === Draw a tile === ''Cost: 1 Crewman'' <Click on the chosen tile at the top of the board.> <br/> === Refresh tiles and Draw === ''Cost: 2 Crewmen'' <Click on the "Renew deck" icon.> The player MUST: # Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve. # Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve. <br/> === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. c31050d599d0cd8bf9a4e6125da90678bf0c3042 1526 1525 2015-05-04T20:13:58Z Savama 7567 wikitext text/x-wiki == '''Північно-Західна Протока [Expedition Northwest Passage]''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. == '''Мета гри''' == Гравець, що здобуває найбільше очок Престижу перемагає. У разі нічиєї, перемагає гравець, що перший повернувся до Гренландії. == '''Опис гри''' == На початку гри кожен гравець отримує: особисте гральне поле, корабель (розміщується на стрілці Гренландія), сани (розміщуються на особистому гральному полі), 7 моряків. Гра триває 10 раундів. Кожен раунд складається з двох фаз: 1) ''Фаза дій'', коли гравці виконують доступні дії; 2) ''Фаза завершення раунду'', коли пересувається Диск Cонця й відбувається підготовка до наступного раунду. == '''Фаза дій''' == Гравець має 7 моряків, що їх можна використати для виконання таких дій: 1) Взяти плитку; 2) Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них; 3) Викласти плитку на гральну дошку; 4) Перевести моряків (з корабля на сани і навпаки); 5) Пересунути корабель або сани; 6) Дослідити; 7) Знайти; 8) Спасувати. На особистому гральному полі гравця є дві зони – "Корабель" та "Сани", що своєю чергою діляться на дві частини "Готові" та "Відпочивальники". Корабель чи Сани можуть виконувати будь-які дії, коли на них є матроси. На початку гри всі моряки перебувають на кораблі. Щойно гравець переводить їх на сани, як здобуває можливість пересувати їх по гральній дошці. Щоб виконати завдання гравець має використати потрібну кількість моряків. Щоб зазначити дію, гравець переміщає потрібну кількість моряків з "Готових" до "Відпочивальників" на кораблі чи на санах. Гравці виконують дії почергово, аж поки всі не спасують. Протягом ходу гравець: - МУСИТЬ виконати одну дію, використовуючи для цього потрібну кількість моряків. Якщо гравець не має "Готових" моряків, то він може лише спасувати. - Після виконання першої дії гравець може виконати одну або більше додаткових дій. Додаткові дії потребують участі на одного моряка більше, ніж зазвичай. == ACTIONS == === Draw a tile === ''Cost: 1 Crewman'' <Click on the chosen tile at the top of the board.> <br/> === Refresh tiles and Draw === ''Cost: 2 Crewmen'' <Click on the "Renew deck" icon.> The player MUST: # Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve. # Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve. <br/> === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. 807c371c894ac17bbb2007569d40234d76dc0e02 1527 1526 2015-05-04T20:15:15Z Savama 7567 wikitext text/x-wiki == '''Північно-Західна Протока [Expedition Northwest Passage]''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. == '''Мета гри''' == Гравець, що здобуває найбільше очок Престижу перемагає. У разі нічиєї, перемагає гравець, що перший повернувся до Гренландії. == '''Опис гри''' == На початку гри кожен гравець отримує: особисте гральне поле, корабель (розміщується на стрілці Гренландія), сани (розміщуються на особистому гральному полі), 7 моряків. Гра триває 10 раундів. Кожен раунд складається з двох фаз: 1) ''Фаза дій'', коли гравці виконують доступні дії; 2) ''Фаза завершення раунду'', коли пересувається Диск Cонця й відбувається підготовка до наступного раунду. == '''Фаза дій''' == Гравець має 7 моряків, що їх можна використати для виконання таких дій: 1) Взяти плитку; 2) Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них; 3) Викласти плитку на гральну дошку; 4) Перевести моряків (з корабля на сани і навпаки); 5) Пересунути корабель або сани; 6) Дослідити; 7) Знайти; 8) Спасувати. На особистому гральному полі гравця є дві зони – "Корабель" та "Сани", що своєю чергою діляться на дві частини "Готові" та "Відпочивальники". Корабель чи Сани можуть виконувати будь-які дії, коли на них є матроси. На початку гри всі моряки перебувають на кораблі. Щойно гравець переводить їх на сани, як здобуває можливість пересувати їх по гральній дошці. Щоб виконати завдання гравець має використати потрібну кількість моряків. Щоб зазначити дію, гравець переміщає потрібну кількість моряків з "Готових" до "Відпочивальників" на кораблі чи на санах. Гравці виконують дії почергово, аж поки всі не спасують. Протягом ходу гравець: - МУСИТЬ виконати одну дію, використовуючи для цього потрібну кількість моряків. Якщо гравець не має "Готових" моряків, то він може лише спасувати. - Після виконання першої дії гравець може виконати одну або більше додаткових дій. Додаткові дії потребують участі на одного моряка більше, ніж зазвичай. == '''Фаза завершення раунду''' == ''1. Пересування Диску Сонця.'' Диск Сонця пересувається на одну позицію проти годинникової стрілки по Сонячній Арці. В основному, ігровий процес полягає в тому, що гравці почергово викладають на гральну дошку плитки "Дослідження". Залежно від раунду гри, гральна дошка може бути в тій чи іншій мірі "замерзлою". Розміщення Диску Сонця визначає, яка частина гральної дошки "замерзає", а яка "тане". - Плитки, що повністю перебувають над роздільчою лінією Диску, вважаються повністю замерзлими. Вода вкривається кригою, і по ній можна пересуватися лише санами. Корабель, що опинився на замерзлій плитці не може рухатися поки не скресне крига. - Плитки, що повністю перебувають під роздільчою лінією Диску, вважаються розмерзлими – сани так само можуть пересуватися островами, а проходи між ними відкриті для судноплавства. Сани, що опинилися на водяній ділянці розмерзлої плитки, треба пересунути або на острівну частину, або на замерзлу. - Плитки, розділені лінією диску пополовині, вважаються замерзлими у верхній частині й розмерзлими в нижній. По верхній частині можуть пересуватися лише сани. Нижня частина, якщо це острів, придатна для пересування саней, або, якщо це вода, придатна для пересування кораблів. Якщо плитка, на якій перебуває корабель, після руху Диску Сонця виявляється розділеною пополовині, корабель пересувається на незамерзлу водяну частину плитки, якщо така є. Якщо після руху Диску Сонця сани не можна пересунути на землю або замерзлу частину тієї ж плитки, всі моряки, що перебувають у санах, втрачаються. ''2. Підготування до наступного раунду.'' - Всі задіяні моряки на особистих гральних полях переміщаються з "Відпочивальників" до "Готових", при цьому моряки не переходять з корабля на сани й навпаки. - Відмітники черговості ходу гравців пересуваються з другої доріжки визначення черговості ходу на першу. == ACTIONS == === Draw a tile === ''Cost: 1 Crewman'' <Click on the chosen tile at the top of the board.> <br/> === Refresh tiles and Draw === ''Cost: 2 Crewmen'' <Click on the "Renew deck" icon.> The player MUST: # Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve. # Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve. <br/> === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. 82d95b7047c90d6b1fa09102361e6f6450b11ecd 1528 1527 2015-05-04T20:15:33Z Savama 7567 wikitext text/x-wiki == '''Північно-Західна Протока [Expedition Northwest Passage]''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. == '''Мета гри''' == Гравець, що здобуває найбільше очок Престижу перемагає. У разі нічиєї, перемагає гравець, що перший повернувся до Гренландії. == '''Опис гри''' == На початку гри кожен гравець отримує: особисте гральне поле, корабель (розміщується на стрілці Гренландія), сани (розміщуються на особистому гральному полі), 7 моряків. Гра триває 10 раундів. Кожен раунд складається з двох фаз: 1) ''Фаза дій'', коли гравці виконують доступні дії; 2) ''Фаза завершення раунду'', коли пересувається Диск Cонця й відбувається підготовка до наступного раунду. == '''Фаза дій''' == Гравець має 7 моряків, що їх можна використати для виконання таких дій: 1) Взяти плитку; 2) Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них; 3) Викласти плитку на гральну дошку; 4) Перевести моряків (з корабля на сани і навпаки); 5) Пересунути корабель або сани; 6) Дослідити; 7) Знайти; 8) Спасувати. На особистому гральному полі гравця є дві зони – "Корабель" та "Сани", що своєю чергою діляться на дві частини "Готові" та "Відпочивальники". Корабель чи Сани можуть виконувати будь-які дії, коли на них є матроси. На початку гри всі моряки перебувають на кораблі. Щойно гравець переводить їх на сани, як здобуває можливість пересувати їх по гральній дошці. Щоб виконати завдання гравець має використати потрібну кількість моряків. Щоб зазначити дію, гравець переміщає потрібну кількість моряків з "Готових" до "Відпочивальників" на кораблі чи на санах. Гравці виконують дії почергово, аж поки всі не спасують. Протягом ходу гравець: - МУСИТЬ виконати одну дію, використовуючи для цього потрібну кількість моряків. Якщо гравець не має "Готових" моряків, то він може лише спасувати. - Після виконання першої дії гравець може виконати одну або більше додаткових дій. Додаткові дії потребують участі на одного моряка більше, ніж зазвичай. == '''Фаза завершення раунду''' == ''1. Пересування Диску Сонця.'' Диск Сонця пересувається на одну позицію проти годинникової стрілки по Сонячній Арці. В основному, ігровий процес полягає в тому, що гравці почергово викладають на гральну дошку плитки "Дослідження". Залежно від раунду гри, гральна дошка може бути в тій чи іншій мірі "замерзлою". Розміщення Диску Сонця визначає, яка частина гральної дошки "замерзає", а яка "тане". - Плитки, що повністю перебувають над роздільчою лінією Диску, вважаються повністю замерзлими. Вода вкривається кригою, і по ній можна пересуватися лише санами. Корабель, що опинився на замерзлій плитці не може рухатися поки не скресне крига. - Плитки, що повністю перебувають під роздільчою лінією Диску, вважаються розмерзлими – сани так само можуть пересуватися островами, а проходи між ними відкриті для судноплавства. Сани, що опинилися на водяній ділянці розмерзлої плитки, треба пересунути або на острівну частину, або на замерзлу. - Плитки, розділені лінією диску пополовині, вважаються замерзлими у верхній частині й розмерзлими в нижній. По верхній частині можуть пересуватися лише сани. Нижня частина, якщо це острів, придатна для пересування саней, або, якщо це вода, придатна для пересування кораблів. Якщо плитка, на якій перебуває корабель, після руху Диску Сонця виявляється розділеною пополовині, корабель пересувається на незамерзлу водяну частину плитки, якщо така є. Якщо після руху Диску Сонця сани не можна пересунути на землю або замерзлу частину тієї ж плитки, всі моряки, що перебувають у санах, втрачаються. ''2. Підготування до наступного раунду.'' - Всі задіяні моряки на особистих гральних полях переміщаються з "Відпочивальників" до "Готових", при цьому моряки не переходять з корабля на сани й навпаки. - Відмітники черговості ходу гравців пересуваються з другої доріжки визначення черговості ходу на першу. == ACTIONS == === Draw a tile === ''Cost: 1 Crewman'' <Click on the chosen tile at the top of the board.> <br/> === Refresh tiles and Draw === ''Cost: 2 Crewmen'' <Click on the "Renew deck" icon.> The player MUST: # Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve. # Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve. <br/> === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. 1a746aac1dd20e0e18cdee6971c13b5fa174d1ac 1529 1528 2015-05-04T20:16:51Z Savama 7567 wikitext text/x-wiki == '''Північно-Західна Протока [Expedition Northwest Passage]''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. == '''Мета гри''' == Гравець, що здобуває найбільше очок Престижу перемагає. У разі нічиєї, перемагає гравець, що перший повернувся до Гренландії. == '''Опис гри''' == На початку гри кожен гравець отримує: особисте гральне поле, корабель (розміщується на стрілці Гренландія), сани (розміщуються на особистому гральному полі), 7 моряків. Гра триває 10 раундів. Кожен раунд складається з двох фаз: 1) ''Фаза дій'', коли гравці виконують доступні дії; 2) ''Фаза завершення раунду'', коли пересувається Диск Cонця й відбувається підготовка до наступного раунду. == '''Фаза дій''' == Гравець має 7 моряків, що їх можна використати для виконання таких дій: 1) Взяти плитку; 2) Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них; 3) Викласти плитку на гральну дошку; 4) Перевести моряків (з корабля на сани і навпаки); 5) Пересунути корабель або сани; 6) Дослідити; 7) Знайти; 8) Спасувати. На особистому гральному полі гравця є дві зони – "Корабель" та "Сани", що своєю чергою діляться на дві частини "Готові" та "Відпочивальники". Корабель чи Сани можуть виконувати будь-які дії, коли на них є матроси. На початку гри всі моряки перебувають на кораблі. Щойно гравець переводить їх на сани, як здобуває можливість пересувати їх по гральній дошці. Щоб виконати завдання гравець має використати потрібну кількість моряків. Щоб зазначити дію, гравець переміщає потрібну кількість моряків з "Готових" до "Відпочивальників" на кораблі чи на санах. Гравці виконують дії почергово, аж поки всі не спасують. Протягом ходу гравець: - МУСИТЬ виконати одну дію, використовуючи для цього потрібну кількість моряків. Якщо гравець не має "Готових" моряків, то він може лише спасувати. - Після виконання першої дії гравець може виконати одну або більше додаткових дій. Додаткові дії потребують участі на одного моряка більше, ніж зазвичай. == '''Фаза завершення раунду''' == ''1. Пересування Диску Сонця.'' Диск Сонця пересувається на одну позицію проти годинникової стрілки по Сонячній Арці. В основному, ігровий процес полягає в тому, що гравці почергово викладають на гральну дошку плитки "Дослідження". Залежно від раунду гри, гральна дошка може бути в тій чи іншій мірі "замерзлою". Розміщення Диску Сонця визначає, яка частина гральної дошки "замерзає", а яка "тане". - Плитки, що повністю перебувають над роздільчою лінією Диску, вважаються повністю замерзлими. Вода вкривається кригою, і по ній можна пересуватися лише санами. Корабель, що опинився на замерзлій плитці не може рухатися поки не скресне крига. - Плитки, що повністю перебувають під роздільчою лінією Диску, вважаються розмерзлими – сани так само можуть пересуватися островами, а проходи між ними відкриті для судноплавства. Сани, що опинилися на водяній ділянці розмерзлої плитки, треба пересунути або на острівну частину, або на замерзлу. - Плитки, розділені лінією диску пополовині, вважаються замерзлими у верхній частині й розмерзлими в нижній. По верхній частині можуть пересуватися лише сани. Нижня частина, якщо це острів, придатна для пересування саней, або, якщо це вода, придатна для пересування кораблів. Якщо плитка, на якій перебуває корабель, після руху Диску Сонця виявляється розділеною пополовині, корабель пересувається на незамерзлу водяну частину плитки, якщо така є. Якщо після руху Диску Сонця сани не можна пересунути на землю або замерзлу частину тієї ж плитки, всі моряки, що перебувають у санах, втрачаються. ''2. Підготування до наступного раунду.'' - Всі задіяні моряки на особистих гральних полях переміщаються з "Відпочивальників" до "Готових", при цьому моряки не переходять з корабля на сани й навпаки. - Відмітники черговості ходу гравців пересуваються з другої доріжки визначення черговості ходу на першу. == '''ОПИС ДІЙ''' == '''Дія 1 – Взяти плитку''' Вартість: 1 моряк Гравець може вибрати:
а) взяти ОДНУ велику плитку з 4 доступних; б) взяти ОДНУ малу плитку з 6 доступних. Гравець бере вибрану плитку й кладе її перед сообою, утворюючи особистий запас. Особистий запас може складатися з будь-якої кількості плиток. === Refresh tiles and Draw === ''Cost: 2 Crewmen'' <Click on the "Renew deck" icon.> The player MUST: # Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve. # Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve. <br/> === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. a5db32bed04d71700d8d268dd920c84388e7e28f 1530 1529 2015-05-04T20:18:13Z Savama 7567 wikitext text/x-wiki == '''Північно-Західна Протока [Expedition Northwest Passage]''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. == '''Мета гри''' == Гравець, що здобуває найбільше очок Престижу перемагає. У разі нічиєї, перемагає гравець, що перший повернувся до Гренландії. == '''Опис гри''' == На початку гри кожен гравець отримує: особисте гральне поле, корабель (розміщується на стрілці Гренландія), сани (розміщуються на особистому гральному полі), 7 моряків. Гра триває 10 раундів. Кожен раунд складається з двох фаз: 1) ''Фаза дій'', коли гравці виконують доступні дії; 2) ''Фаза завершення раунду'', коли пересувається Диск Cонця й відбувається підготовка до наступного раунду. == '''Фаза дій''' == Гравець має 7 моряків, що їх можна використати для виконання таких дій: 1) Взяти плитку; 2) Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них; 3) Викласти плитку на гральну дошку; 4) Перевести моряків (з корабля на сани і навпаки); 5) Пересунути корабель або сани; 6) Дослідити; 7) Знайти; 8) Спасувати. На особистому гральному полі гравця є дві зони – "Корабель" та "Сани", що своєю чергою діляться на дві частини "Готові" та "Відпочивальники". Корабель чи Сани можуть виконувати будь-які дії, коли на них є матроси. На початку гри всі моряки перебувають на кораблі. Щойно гравець переводить їх на сани, як здобуває можливість пересувати їх по гральній дошці. Щоб виконати завдання гравець має використати потрібну кількість моряків. Щоб зазначити дію, гравець переміщає потрібну кількість моряків з "Готових" до "Відпочивальників" на кораблі чи на санах. Гравці виконують дії почергово, аж поки всі не спасують. Протягом ходу гравець: - МУСИТЬ виконати одну дію, використовуючи для цього потрібну кількість моряків. Якщо гравець не має "Готових" моряків, то він може лише спасувати. - Після виконання першої дії гравець може виконати одну або більше додаткових дій. Додаткові дії потребують участі на одного моряка більше, ніж зазвичай. == '''Фаза завершення раунду''' == ''1. Пересування Диску Сонця.'' Диск Сонця пересувається на одну позицію проти годинникової стрілки по Сонячній Арці. В основному, ігровий процес полягає в тому, що гравці почергово викладають на гральну дошку плитки "Дослідження". Залежно від раунду гри, гральна дошка може бути в тій чи іншій мірі "замерзлою". Розміщення Диску Сонця визначає, яка частина гральної дошки "замерзає", а яка "тане". - Плитки, що повністю перебувають над роздільчою лінією Диску, вважаються повністю замерзлими. Вода вкривається кригою, і по ній можна пересуватися лише санами. Корабель, що опинився на замерзлій плитці не може рухатися поки не скресне крига. - Плитки, що повністю перебувають під роздільчою лінією Диску, вважаються розмерзлими – сани так само можуть пересуватися островами, а проходи між ними відкриті для судноплавства. Сани, що опинилися на водяній ділянці розмерзлої плитки, треба пересунути або на острівну частину, або на замерзлу. - Плитки, розділені лінією диску пополовині, вважаються замерзлими у верхній частині й розмерзлими в нижній. По верхній частині можуть пересуватися лише сани. Нижня частина, якщо це острів, придатна для пересування саней, або, якщо це вода, придатна для пересування кораблів. Якщо плитка, на якій перебуває корабель, після руху Диску Сонця виявляється розділеною пополовині, корабель пересувається на незамерзлу водяну частину плитки, якщо така є. Якщо після руху Диску Сонця сани не можна пересунути на землю або замерзлу частину тієї ж плитки, всі моряки, що перебувають у санах, втрачаються. ''2. Підготування до наступного раунду.'' - Всі задіяні моряки на особистих гральних полях переміщаються з "Відпочивальників" до "Готових", при цьому моряки не переходять з корабля на сани й навпаки. - Відмітники черговості ходу гравців пересуваються з другої доріжки визначення черговості ходу на першу. == '''ОПИС ДІЙ''' == '''Дія 1 – Взяти плитку''' Вартість: 1 моряк Гравець може вибрати:
а) взяти ОДНУ велику плитку з 4 доступних; б) взяти ОДНУ малу плитку з 6 доступних. Гравець бере вибрану плитку й кладе її перед сообою, утворюючи особистий запас. Особистий запас може складатися з будь-якої кількості плиток. '''Дія 2 – Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них''' Вартість: 2 моряки Гравець МУСИТЬ: 1 – Оновити великі плитки: гравець витягує 4 великих плитки й заміщує ними вже викладені великі плитки. Старі плитки повертаються до резерву. 2 – Взяти плитку: гравець бере велику або малу плитку Дослідження й кладе її до особистого запасу. Пунктирні лінії на плитці допомагають розміщувати їх на дошку; на рух вони не впливають. Корабель, що перебуває на плитці, має доступ до будь-якої її водної ділянки, не вкритої кригою, тому гравець може розмістити корабель у будь-якій частині цієї плитки. === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. 723d75a4936bc60f19d7141b2113ab75f0388d2a 1531 1530 2015-05-04T20:18:34Z Savama 7567 wikitext text/x-wiki == '''Північно-Західна Протока [Expedition Northwest Passage]''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. == '''Мета гри''' == Гравець, що здобуває найбільше очок Престижу перемагає. У разі нічиєї, перемагає гравець, що перший повернувся до Гренландії. == '''Опис гри''' == На початку гри кожен гравець отримує: ''особисте гральне поле'', корабель (розміщується на стрілці Гренландія), сани (розміщуються на особистому гральному полі), 7 моряків. Гра триває 10 раундів. Кожен раунд складається з двох фаз: 1) ''Фаза дій'', коли гравці виконують доступні дії; 2) ''Фаза завершення раунду'', коли пересувається Диск Cонця й відбувається підготовка до наступного раунду. == '''Фаза дій''' == Гравець має 7 моряків, що їх можна використати для виконання таких дій: 1) Взяти плитку; 2) Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них; 3) Викласти плитку на гральну дошку; 4) Перевести моряків (з корабля на сани і навпаки); 5) Пересунути корабель або сани; 6) Дослідити; 7) Знайти; 8) Спасувати. На особистому гральному полі гравця є дві зони – "Корабель" та "Сани", що своєю чергою діляться на дві частини "Готові" та "Відпочивальники". Корабель чи Сани можуть виконувати будь-які дії, коли на них є матроси. На початку гри всі моряки перебувають на кораблі. Щойно гравець переводить їх на сани, як здобуває можливість пересувати їх по гральній дошці. Щоб виконати завдання гравець має використати потрібну кількість моряків. Щоб зазначити дію, гравець переміщає потрібну кількість моряків з "Готових" до "Відпочивальників" на кораблі чи на санах. Гравці виконують дії почергово, аж поки всі не спасують. Протягом ходу гравець: - МУСИТЬ виконати одну дію, використовуючи для цього потрібну кількість моряків. Якщо гравець не має "Готових" моряків, то він може лише спасувати. - Після виконання першої дії гравець може виконати одну або більше додаткових дій. Додаткові дії потребують участі на одного моряка більше, ніж зазвичай. == '''Фаза завершення раунду''' == ''1. Пересування Диску Сонця.'' Диск Сонця пересувається на одну позицію проти годинникової стрілки по Сонячній Арці. В основному, ігровий процес полягає в тому, що гравці почергово викладають на гральну дошку плитки "Дослідження". Залежно від раунду гри, гральна дошка може бути в тій чи іншій мірі "замерзлою". Розміщення Диску Сонця визначає, яка частина гральної дошки "замерзає", а яка "тане". - Плитки, що повністю перебувають над роздільчою лінією Диску, вважаються повністю замерзлими. Вода вкривається кригою, і по ній можна пересуватися лише санами. Корабель, що опинився на замерзлій плитці не може рухатися поки не скресне крига. - Плитки, що повністю перебувають під роздільчою лінією Диску, вважаються розмерзлими – сани так само можуть пересуватися островами, а проходи між ними відкриті для судноплавства. Сани, що опинилися на водяній ділянці розмерзлої плитки, треба пересунути або на острівну частину, або на замерзлу. - Плитки, розділені лінією диску пополовині, вважаються замерзлими у верхній частині й розмерзлими в нижній. По верхній частині можуть пересуватися лише сани. Нижня частина, якщо це острів, придатна для пересування саней, або, якщо це вода, придатна для пересування кораблів. Якщо плитка, на якій перебуває корабель, після руху Диску Сонця виявляється розділеною пополовині, корабель пересувається на незамерзлу водяну частину плитки, якщо така є. Якщо після руху Диску Сонця сани не можна пересунути на землю або замерзлу частину тієї ж плитки, всі моряки, що перебувають у санах, втрачаються. ''2. Підготування до наступного раунду.'' - Всі задіяні моряки на особистих гральних полях переміщаються з "Відпочивальників" до "Готових", при цьому моряки не переходять з корабля на сани й навпаки. - Відмітники черговості ходу гравців пересуваються з другої доріжки визначення черговості ходу на першу. == '''ОПИС ДІЙ''' == '''Дія 1 – Взяти плитку''' Вартість: 1 моряк Гравець може вибрати:
а) взяти ОДНУ велику плитку з 4 доступних; б) взяти ОДНУ малу плитку з 6 доступних. Гравець бере вибрану плитку й кладе її перед сообою, утворюючи особистий запас. Особистий запас може складатися з будь-якої кількості плиток. '''Дія 2 – Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них''' Вартість: 2 моряки Гравець МУСИТЬ: 1 – Оновити великі плитки: гравець витягує 4 великих плитки й заміщує ними вже викладені великі плитки. Старі плитки повертаються до резерву. 2 – Взяти плитку: гравець бере велику або малу плитку Дослідження й кладе її до особистого запасу. Пунктирні лінії на плитці допомагають розміщувати їх на дошку; на рух вони не впливають. Корабель, що перебуває на плитці, має доступ до будь-якої її водної ділянки, не вкритої кригою, тому гравець може розмістити корабель у будь-якій частині цієї плитки. === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. 451b7dcc58e15623e90111e1a6cf06a383888ab9 1532 1531 2015-05-04T20:23:24Z Savama 7567 wikitext text/x-wiki == '''Північно-Західна Протока [Expedition Northwest Passage]''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. == '''Мета гри''' == Гравець, що здобуває найбільше очок Престижу перемагає. У разі нічиєї, перемагає гравець, що перший повернувся до Гренландії. == '''Опис гри''' == На початку гри кожен гравець отримує: ''особисте гральне поле'', корабель (розміщується на стрілці Гренландія), сани (розміщуються на особистому гральному полі), 7 моряків. Гра триває 10 раундів. Кожен раунд складається з двох фаз: 1) ''Фаза дій'', коли гравці виконують доступні дії; 2) ''Фаза завершення раунду'', коли пересувається Диск Cонця й відбувається підготовка до наступного раунду. == '''Фаза дій''' == Гравець має 7 моряків, що їх можна використати для виконання таких дій: 1) Взяти плитку; 2) Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них; 3) Викласти плитку на гральну дошку; 4) Перевести моряків (з корабля на сани і навпаки); 5) Пересунути корабель або сани; 6) Дослідити; 7) Знайти; 8) Спасувати. На особистому гральному полі гравця є дві зони – "Корабель" та "Сани", що своєю чергою діляться на дві частини "Готові" та "Відпочивальники". Корабель чи Сани можуть виконувати будь-які дії, коли на них є матроси. На початку гри всі моряки перебувають на кораблі. Щойно гравець переводить їх на сани, як здобуває можливість пересувати їх по гральній дошці. Щоб виконати завдання гравець має використати потрібну кількість моряків. Щоб зазначити дію, гравець переміщає потрібну кількість моряків з "Готових" до "Відпочивальників" на кораблі чи на санах. Гравці виконують дії почергово, аж поки всі не спасують. Протягом ходу гравець: - МУСИТЬ виконати одну дію, використовуючи для цього потрібну кількість моряків. Якщо гравець не має "Готових" моряків, то він може лише спасувати. - Після виконання першої дії гравець може виконати одну або більше додаткових дій. Додаткові дії потребують участі на одного моряка більше, ніж зазвичай. == '''Фаза завершення раунду''' == ''1. Пересування Диску Сонця.'' Диск Сонця пересувається на одну позицію проти годинникової стрілки по Сонячній Арці. В основному, ігровий процес полягає в тому, що гравці почергово викладають на гральну дошку плитки "Дослідження". Залежно від раунду гри, гральна дошка може бути в тій чи іншій мірі "замерзлою". Розміщення Диску Сонця визначає, яка частина гральної дошки "замерзає", а яка "тане". - Плитки, що повністю перебувають над роздільчою лінією Диску, вважаються повністю замерзлими. Вода вкривається кригою, і по ній можна пересуватися лише санами. Корабель, що опинився на замерзлій плитці не може рухатися поки не скресне крига. - Плитки, що повністю перебувають під роздільчою лінією Диску, вважаються розмерзлими – сани так само можуть пересуватися островами, а проходи між ними відкриті для судноплавства. Сани, що опинилися на водяній ділянці розмерзлої плитки, треба пересунути або на острівну частину, або на замерзлу. - Плитки, розділені лінією диску пополовині, вважаються замерзлими у верхній частині й розмерзлими в нижній. По верхній частині можуть пересуватися лише сани. Нижня частина, якщо це острів, придатна для пересування саней, або, якщо це вода, придатна для пересування кораблів. Якщо плитка, на якій перебуває корабель, після руху Диску Сонця виявляється розділеною пополовині, корабель пересувається на незамерзлу водяну частину плитки, якщо така є. Якщо після руху Диску Сонця сани не можна пересунути на землю або замерзлу частину тієї ж плитки, всі моряки, що перебувають у санах, втрачаються. ''2. Підготування до наступного раунду.'' - Всі задіяні моряки на особистих гральних полях переміщаються з "Відпочивальників" до "Готових", при цьому моряки не переходять з корабля на сани й навпаки. - Відмітники черговості ходу гравців пересуваються з другої доріжки визначення черговості ходу на першу. == '''ОПИС ДІЙ''' == '''Дія 1 – Взяти плитку''' Вартість: 1 моряк Гравець може вибрати:
а) взяти ОДНУ велику плитку з 4 доступних; б) взяти ОДНУ малу плитку з 6 доступних. Гравець бере вибрану плитку й кладе її перед сообою, утворюючи особистий запас. Особистий запас може складатися з будь-якої кількості плиток. '''Дія 2 – Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них''' Вартість: 2 моряки Гравець МУСИТЬ: 1 – Оновити великі плитки: гравець витягує 4 великих плитки й заміщує ними вже викладені великі плитки. Старі плитки повертаються до резерву. 2 – Взяти плитку: гравець бере велику або малу плитку Дослідження й кладе її до особистого запасу. Пунктирні лінії на плитці допомагають розміщувати їх на дошку; на рух вони не впливають. Корабель, що перебуває на плитці, має доступ до будь-якої її водної ділянки, не вкритої кригою, тому гравець може розмістити корабель у будь-якій частині цієї плитки. === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. 02ab857cfdb882d08c6b3713e52f24b5a822f4c2 1533 1532 2015-05-04T20:32:47Z Savama 7567 wikitext text/x-wiki == '''Північно-Західна Протока [Expedition Northwest Passage]''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. == '''Мета гри''' == Гравець, що здобуває найбільше очок Престижу перемагає. У разі нічиєї, перемагає гравець, що перший повернувся до Гренландії. == '''Опис гри''' == На початку гри кожен гравець отримує: ''особисте гральне поле'', корабель (розміщується на стрілці Гренландія), сани (розміщуються на особистому гральному полі), 7 моряків. Гра триває 10 раундів. Кожен раунд складається з двох фаз: 1) ''Фаза дій'', коли гравці виконують доступні дії; 2) ''Фаза завершення раунду'', коли пересувається Диск Cонця й відбувається підготовка до наступного раунду. == '''Фаза дій''' == Гравець має 7 моряків, що їх можна використати для виконання таких дій: 1) Взяти плитку; 2) Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них; 3) Викласти плитку на гральну дошку; 4) Перевести моряків (з корабля на сани і навпаки); 5) Пересунути корабель або сани; 6) Дослідити; 7) Знайти; 8) Спасувати. На особистому гральному полі гравця є дві зони – "Корабель" та "Сани", що своєю чергою діляться на дві частини "Готові" та "Відпочивальники". Корабель чи Сани можуть виконувати будь-які дії, коли на них є матроси. На початку гри всі моряки перебувають на кораблі. Щойно гравець переводить їх на сани, як здобуває можливість пересувати їх по гральній дошці. Щоб виконати завдання гравець має використати потрібну кількість моряків. Щоб зазначити дію, гравець переміщає потрібну кількість моряків з "Готових" до "Відпочивальників" на кораблі чи на санах. Гравці виконують дії почергово, аж поки всі не спасують. Протягом ходу гравець: - МУСИТЬ виконати одну дію, використовуючи для цього потрібну кількість моряків. Якщо гравець не має "Готових" моряків, то він може лише спасувати. - Після виконання першої дії гравець може виконати одну або більше додаткових дій. Додаткові дії потребують участі на одного моряка більше, ніж зазвичай. == '''Фаза завершення раунду''' == ''1. Пересування Диску Сонця.'' Диск Сонця пересувається на одну позицію проти годинникової стрілки по Сонячній Арці. В основному, ігровий процес полягає в тому, що гравці почергово викладають на гральну дошку плитки "Дослідження". Залежно від раунду гри, гральна дошка може бути в тій чи іншій мірі "замерзлою". Розміщення Диску Сонця визначає, яка частина гральної дошки "замерзає", а яка "тане". - Плитки, що повністю перебувають над роздільчою лінією Диску, вважаються повністю замерзлими. Вода вкривається кригою, і по ній можна пересуватися лише санами. Корабель, що опинився на замерзлій плитці не може рухатися поки не скресне крига. - Плитки, що повністю перебувають під роздільчою лінією Диску, вважаються розмерзлими – сани так само можуть пересуватися островами, а проходи між ними відкриті для судноплавства. Сани, що опинилися на водяній ділянці розмерзлої плитки, треба пересунути або на острівну частину, або на замерзлу. - Плитки, розділені лінією диску пополовині, вважаються замерзлими у верхній частині й розмерзлими в нижній. По верхній частині можуть пересуватися лише сани. Нижня частина, якщо це острів, придатна для пересування саней, або, якщо це вода, придатна для пересування кораблів. Якщо плитка, на якій перебуває корабель, після руху Диску Сонця виявляється розділеною пополовині, корабель пересувається на незамерзлу водяну частину плитки, якщо така є. Якщо після руху Диску Сонця сани не можна пересунути на землю або замерзлу частину тієї ж плитки, всі моряки, що перебувають у санах, втрачаються. ''2. Підготування до наступного раунду.'' - Всі задіяні моряки на особистих гральних полях переміщаються з "Відпочивальників" до "Готових", при цьому моряки не переходять з корабля на сани й навпаки. - Відмітники черговості ходу гравців пересуваються з другої доріжки визначення черговості ходу на першу. == '''ОПИС ДІЙ''' == '''Дія 1 – Взяти плитку''' Вартість: 1 моряк Гравець може вибрати:
а) взяти ОДНУ велику плитку з 4 доступних; б) взяти ОДНУ малу плитку з 6 доступних. Гравець бере вибрану плитку й кладе її перед сообою, утворюючи особистий запас. Особистий запас може складатися з будь-якої кількості плиток. '''Дія 2 – Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них''' Вартість: 2 моряки Гравець МУСИТЬ: 1 – Оновити великі плитки: гравець витягує 4 великих плитки й заміщує ними вже викладені великі плитки. Старі плитки повертаються до резерву. 2 – Взяти плитку: гравець бере велику або малу плитку Дослідження й кладе її до особистого запасу. Пунктирні лінії на плитці допомагають розміщувати їх на дошку; на рух вони не впливають. Корабель, що перебуває на плитці, має доступ до будь-якої її водної ділянки, не вкритої кригою, тому гравець може розмістити корабель у будь-якій частині цієї плитки. '''Дія 3 – Викласти плитку на гральну дошку''' Вартість: 1 моряк Гравець розміщує на гральній дошці ОДНУ плитку, що бере з особистого запасу, дотримуючись таких умов: - Плитка мусить вписуватися в пунктирну сітку гральної дошки. - Малі плитки Дослідження слід класти на дошку стороною Жослідження догори (з дідянками води й/або землі); великі плитки Дослідження можна класти будь-якою стороною. - Плитка Дослідження має бути викладена так, щоб принаймні однією своєю стороною торкатися або зображеної на полі плитки, або вже викладеної плитки, на якій перебуває корабель чи сани гравця. - Розміщуючи нову плитку стежте за тим, ощб межі суші й моря співпадали з межами уже викладених плиток. - Плитку не можна розмітити так, щоб заблокувати морський шлях з Гренландії до Північно-Західної Протоки. Якщо на щойно розміщеній плитці зображено спеціяльний символ, то на плитку одразу кладуть відповідний жетон. ''Жетони Мапування'' Острів повністю утворено, якщо ділянки хоча б двох дотичних плиток повністю оточені водою або обмежені краєм гральної дошки. Коли, розміщуючи плитку на дошці чи заповнюючи порожне місце, гравець утворює острів, то бере з режерву жетон "Мапування" і кладе собі на особисте гральне поле. Також він хдобуває стільки очок Престижу, скільки плиток утворюють цей острів. Якщо, розміщуючи плитку, гравець утворює декілька островів, він здобуває стільки жетонів "Мапування", скільки островів він утворив, і здобуває очки Престижу за кожен острів окремо. === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. 27088732feb19cc7b8adef78ffbdaf1354071991 1534 1533 2015-05-04T20:33:08Z Savama 7567 wikitext text/x-wiki == '''Північно-Західна Протока [Expedition Northwest Passage]''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. == '''Мета гри''' == Гравець, що здобуває найбільше очок Престижу перемагає. У разі нічиєї, перемагає гравець, що перший повернувся до Гренландії. == '''Опис гри''' == На початку гри кожен гравець отримує: ''особисте гральне поле'', корабель (розміщується на стрілці Гренландія), сани (розміщуються на особистому гральному полі), 7 моряків. Гра триває 10 раундів. Кожен раунд складається з двох фаз: 1) ''Фаза дій'', коли гравці виконують доступні дії; 2) ''Фаза завершення раунду'', коли пересувається Диск Cонця й відбувається підготовка до наступного раунду. == '''Фаза дій''' == Гравець має 7 моряків, що їх можна використати для виконання таких дій: 1) Взяти плитку; 2) Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них; 3) Викласти плитку на гральну дошку; 4) Перевести моряків (з корабля на сани і навпаки); 5) Пересунути корабель або сани; 6) Дослідити; 7) Знайти; 8) Спасувати. На особистому гральному полі гравця є дві зони – "Корабель" та "Сани", що своєю чергою діляться на дві частини "Готові" та "Відпочивальники". Корабель чи Сани можуть виконувати будь-які дії, коли на них є матроси. На початку гри всі моряки перебувають на кораблі. Щойно гравець переводить їх на сани, як здобуває можливість пересувати їх по гральній дошці. Щоб виконати завдання гравець має використати потрібну кількість моряків. Щоб зазначити дію, гравець переміщає потрібну кількість моряків з "Готових" до "Відпочивальників" на кораблі чи на санах. Гравці виконують дії почергово, аж поки всі не спасують. Протягом ходу гравець: - МУСИТЬ виконати одну дію, використовуючи для цього потрібну кількість моряків. Якщо гравець не має "Готових" моряків, то він може лише спасувати. - Після виконання першої дії гравець може виконати одну або більше додаткових дій. Додаткові дії потребують участі на одного моряка більше, ніж зазвичай. == '''Фаза завершення раунду''' == ''1. Пересування Диску Сонця.'' Диск Сонця пересувається на одну позицію проти годинникової стрілки по Сонячній Арці. В основному, ігровий процес полягає в тому, що гравці почергово викладають на гральну дошку плитки "Дослідження". Залежно від раунду гри, гральна дошка може бути в тій чи іншій мірі "замерзлою". Розміщення Диску Сонця визначає, яка частина гральної дошки "замерзає", а яка "тане". - Плитки, що повністю перебувають над роздільчою лінією Диску, вважаються повністю замерзлими. Вода вкривається кригою, і по ній можна пересуватися лише санами. Корабель, що опинився на замерзлій плитці не може рухатися поки не скресне крига. - Плитки, що повністю перебувають під роздільчою лінією Диску, вважаються розмерзлими – сани так само можуть пересуватися островами, а проходи між ними відкриті для судноплавства. Сани, що опинилися на водяній ділянці розмерзлої плитки, треба пересунути або на острівну частину, або на замерзлу. - Плитки, розділені лінією диску пополовині, вважаються замерзлими у верхній частині й розмерзлими в нижній. По верхній частині можуть пересуватися лише сани. Нижня частина, якщо це острів, придатна для пересування саней, або, якщо це вода, придатна для пересування кораблів. Якщо плитка, на якій перебуває корабель, після руху Диску Сонця виявляється розділеною пополовині, корабель пересувається на незамерзлу водяну частину плитки, якщо така є. Якщо після руху Диску Сонця сани не можна пересунути на землю або замерзлу частину тієї ж плитки, всі моряки, що перебувають у санах, втрачаються. ''2. Підготування до наступного раунду.'' - Всі задіяні моряки на особистих гральних полях переміщаються з "Відпочивальників" до "Готових", при цьому моряки не переходять з корабля на сани й навпаки. - Відмітники черговості ходу гравців пересуваються з другої доріжки визначення черговості ходу на першу. == '''ОПИС ДІЙ''' == '''Дія 1 – Взяти плитку''' Вартість: 1 моряк Гравець може вибрати:
а) взяти ОДНУ велику плитку з 4 доступних; б) взяти ОДНУ малу плитку з 6 доступних. Гравець бере вибрану плитку й кладе її перед сообою, утворюючи особистий запас. Особистий запас може складатися з будь-якої кількості плиток. '''Дія 2 – Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них''' Вартість: 2 моряки Гравець МУСИТЬ: 1 – Оновити великі плитки: гравець витягує 4 великих плитки й заміщує ними вже викладені великі плитки. Старі плитки повертаються до резерву. 2 – Взяти плитку: гравець бере велику або малу плитку Дослідження й кладе її до особистого запасу. Пунктирні лінії на плитці допомагають розміщувати їх на дошку; на рух вони не впливають. Корабель, що перебуває на плитці, має доступ до будь-якої її водної ділянки, не вкритої кригою, тому гравець може розмістити корабель у будь-якій частині цієї плитки. '''Дія 3 – Викласти плитку на гральну дошку''' Вартість: 1 моряк Гравець розміщує на гральній дошці ОДНУ плитку, що бере з особистого запасу, дотримуючись таких умов: - Плитка мусить вписуватися в пунктирну сітку гральної дошки. - Малі плитки Дослідження слід класти на дошку стороною Жослідження догори (з дідянками води й/або землі); великі плитки Дослідження можна класти будь-якою стороною. - Плитка Дослідження має бути викладена так, щоб принаймні однією своєю стороною торкатися або зображеної на полі плитки, або вже викладеної плитки, на якій перебуває корабель чи сани гравця. - Розміщуючи нову плитку стежте за тим, ощб межі суші й моря співпадали з межами уже викладених плиток. - Плитку не можна розмітити так, щоб заблокувати морський шлях з Гренландії до Північно-Західної Протоки. Якщо на щойно розміщеній плитці зображено спеціяльний символ, то на плитку одразу кладуть відповідний жетон. ''Жетони Мапування'' Острів повністю утворено, якщо ділянки хоча б двох дотичних плиток повністю оточені водою або обмежені краєм гральної дошки. Коли, розміщуючи плитку на дошці чи заповнюючи порожне місце, гравець утворює острів, то бере з режерву жетон "Мапування" і кладе собі на особисте гральне поле. Також він хдобуває стільки очок Престижу, скільки плиток утворюють цей острів. Якщо, розміщуючи плитку, гравець утворює декілька островів, він здобуває стільки жетонів "Мапування", скільки островів він утворив, і здобуває очки Престижу за кожен острів окремо. === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. 6de0be049742a73b7b67604f40f5d029a1998627 1535 1534 2015-05-04T20:33:38Z Savama 7567 /* ОПИС ДІЙ */ wikitext text/x-wiki == '''Північно-Західна Протока [Expedition Northwest Passage]''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. == '''Мета гри''' == Гравець, що здобуває найбільше очок Престижу перемагає. У разі нічиєї, перемагає гравець, що перший повернувся до Гренландії. == '''Опис гри''' == На початку гри кожен гравець отримує: ''особисте гральне поле'', корабель (розміщується на стрілці Гренландія), сани (розміщуються на особистому гральному полі), 7 моряків. Гра триває 10 раундів. Кожен раунд складається з двох фаз: 1) ''Фаза дій'', коли гравці виконують доступні дії; 2) ''Фаза завершення раунду'', коли пересувається Диск Cонця й відбувається підготовка до наступного раунду. == '''Фаза дій''' == Гравець має 7 моряків, що їх можна використати для виконання таких дій: 1) Взяти плитку; 2) Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них; 3) Викласти плитку на гральну дошку; 4) Перевести моряків (з корабля на сани і навпаки); 5) Пересунути корабель або сани; 6) Дослідити; 7) Знайти; 8) Спасувати. На особистому гральному полі гравця є дві зони – "Корабель" та "Сани", що своєю чергою діляться на дві частини "Готові" та "Відпочивальники". Корабель чи Сани можуть виконувати будь-які дії, коли на них є матроси. На початку гри всі моряки перебувають на кораблі. Щойно гравець переводить їх на сани, як здобуває можливість пересувати їх по гральній дошці. Щоб виконати завдання гравець має використати потрібну кількість моряків. Щоб зазначити дію, гравець переміщає потрібну кількість моряків з "Готових" до "Відпочивальників" на кораблі чи на санах. Гравці виконують дії почергово, аж поки всі не спасують. Протягом ходу гравець: - МУСИТЬ виконати одну дію, використовуючи для цього потрібну кількість моряків. Якщо гравець не має "Готових" моряків, то він може лише спасувати. - Після виконання першої дії гравець може виконати одну або більше додаткових дій. Додаткові дії потребують участі на одного моряка більше, ніж зазвичай. == '''Фаза завершення раунду''' == ''1. Пересування Диску Сонця.'' Диск Сонця пересувається на одну позицію проти годинникової стрілки по Сонячній Арці. В основному, ігровий процес полягає в тому, що гравці почергово викладають на гральну дошку плитки "Дослідження". Залежно від раунду гри, гральна дошка може бути в тій чи іншій мірі "замерзлою". Розміщення Диску Сонця визначає, яка частина гральної дошки "замерзає", а яка "тане". - Плитки, що повністю перебувають над роздільчою лінією Диску, вважаються повністю замерзлими. Вода вкривається кригою, і по ній можна пересуватися лише санами. Корабель, що опинився на замерзлій плитці не може рухатися поки не скресне крига. - Плитки, що повністю перебувають під роздільчою лінією Диску, вважаються розмерзлими – сани так само можуть пересуватися островами, а проходи між ними відкриті для судноплавства. Сани, що опинилися на водяній ділянці розмерзлої плитки, треба пересунути або на острівну частину, або на замерзлу. - Плитки, розділені лінією диску пополовині, вважаються замерзлими у верхній частині й розмерзлими в нижній. По верхній частині можуть пересуватися лише сани. Нижня частина, якщо це острів, придатна для пересування саней, або, якщо це вода, придатна для пересування кораблів. Якщо плитка, на якій перебуває корабель, після руху Диску Сонця виявляється розділеною пополовині, корабель пересувається на незамерзлу водяну частину плитки, якщо така є. Якщо після руху Диску Сонця сани не можна пересунути на землю або замерзлу частину тієї ж плитки, всі моряки, що перебувають у санах, втрачаються. ''2. Підготування до наступного раунду.'' - Всі задіяні моряки на особистих гральних полях переміщаються з "Відпочивальників" до "Готових", при цьому моряки не переходять з корабля на сани й навпаки. - Відмітники черговості ходу гравців пересуваються з другої доріжки визначення черговості ходу на першу. == '''ОПИС ДІЙ''' == '''Дія 1 – Взяти плитку''' Вартість: 1 моряк Гравець може вибрати:
а) взяти ОДНУ велику плитку з 4 доступних; б) взяти ОДНУ малу плитку з 6 доступних. Гравець бере вибрану плитку й кладе її перед сообою, утворюючи особистий запас. Особистий запас може складатися з будь-якої кількості плиток. '''Дія 2 – Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них''' Вартість: 2 моряки Гравець МУСИТЬ: 1 – Оновити великі плитки: гравець витягує 4 великих плитки й заміщує ними вже викладені великі плитки. Старі плитки повертаються до резерву. 2 – Взяти плитку: гравець бере велику або малу плитку Дослідження й кладе її до особистого запасу. Пунктирні лінії на плитці допомагають розміщувати їх на дошку; на рух вони не впливають. Корабель, що перебуває на плитці, має доступ до будь-якої її водної ділянки, не вкритої кригою, тому гравець може розмістити корабель у будь-якій частині цієї плитки. '''Дія 3 – Викласти плитку на гральну дошку''' Вартість: 1 моряк Гравець розміщує на гральній дошці ОДНУ плитку, що бере з особистого запасу, дотримуючись таких умов: - Плитка мусить вписуватися в пунктирну сітку гральної дошки. - Малі плитки Дослідження слід класти на дошку стороною Жослідження догори (з дідянками води й/або землі); великі плитки Дослідження можна класти будь-якою стороною. - Плитка Дослідження має бути викладена так, щоб принаймні однією своєю стороною торкатися або зображеної на полі плитки, або вже викладеної плитки, на якій перебуває корабель чи сани гравця. - Розміщуючи нову плитку стежте за тим, ощб межі суші й моря співпадали з межами уже викладених плиток. - Плитку не можна розмітити так, щоб заблокувати морський шлях з Гренландії до Північно-Західної Протоки. Якщо на щойно розміщеній плитці зображено спеціяльний символ, то на плитку одразу кладуть відповідний жетон. ''Жетони Мапування'' Острів повністю утворився, якщо ділянки хоча б двох дотичних плиток повністю оточені водою або обмежені краєм гральної дошки. Коли, розміщуючи плитку на дошці чи заповнюючи порожне місце, гравець утворює острів, то бере з режерву жетон "Мапування" і кладе собі на особисте гральне поле. Також він хдобуває стільки очок Престижу, скільки плиток утворюють цей острів. Якщо, розміщуючи плитку, гравець утворює декілька островів, він здобуває стільки жетонів "Мапування", скільки островів він утворив, і здобуває очки Престижу за кожен острів окремо. === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. dd50c46d425e72631da0cca2f035b1581faeed0e 1536 1535 2015-05-04T21:00:39Z Savama 7567 Undo revision 1535 by [[Special:Contributions/Savama|Savama]] ([[User talk:Savama|talk]]) wikitext text/x-wiki == '''Північно-Західна Протока [Expedition Northwest Passage]''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. == '''Мета гри''' == Гравець, що здобуває найбільше очок Престижу перемагає. У разі нічиєї, перемагає гравець, що перший повернувся до Гренландії. == '''Опис гри''' == На початку гри кожен гравець отримує: ''особисте гральне поле'', корабель (розміщується на стрілці Гренландія), сани (розміщуються на особистому гральному полі), 7 моряків. Гра триває 10 раундів. Кожен раунд складається з двох фаз: 1) ''Фаза дій'', коли гравці виконують доступні дії; 2) ''Фаза завершення раунду'', коли пересувається Диск Cонця й відбувається підготовка до наступного раунду. == '''Фаза дій''' == Гравець має 7 моряків, що їх можна використати для виконання таких дій: 1) Взяти плитку; 2) Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них; 3) Викласти плитку на гральну дошку; 4) Перевести моряків (з корабля на сани і навпаки); 5) Пересунути корабель або сани; 6) Дослідити; 7) Знайти; 8) Спасувати. На особистому гральному полі гравця є дві зони – "Корабель" та "Сани", що своєю чергою діляться на дві частини "Готові" та "Відпочивальники". Корабель чи Сани можуть виконувати будь-які дії, коли на них є матроси. На початку гри всі моряки перебувають на кораблі. Щойно гравець переводить їх на сани, як здобуває можливість пересувати їх по гральній дошці. Щоб виконати завдання гравець має використати потрібну кількість моряків. Щоб зазначити дію, гравець переміщає потрібну кількість моряків з "Готових" до "Відпочивальників" на кораблі чи на санах. Гравці виконують дії почергово, аж поки всі не спасують. Протягом ходу гравець: - МУСИТЬ виконати одну дію, використовуючи для цього потрібну кількість моряків. Якщо гравець не має "Готових" моряків, то він може лише спасувати. - Після виконання першої дії гравець може виконати одну або більше додаткових дій. Додаткові дії потребують участі на одного моряка більше, ніж зазвичай. == '''Фаза завершення раунду''' == ''1. Пересування Диску Сонця.'' Диск Сонця пересувається на одну позицію проти годинникової стрілки по Сонячній Арці. В основному, ігровий процес полягає в тому, що гравці почергово викладають на гральну дошку плитки "Дослідження". Залежно від раунду гри, гральна дошка може бути в тій чи іншій мірі "замерзлою". Розміщення Диску Сонця визначає, яка частина гральної дошки "замерзає", а яка "тане". - Плитки, що повністю перебувають над роздільчою лінією Диску, вважаються повністю замерзлими. Вода вкривається кригою, і по ній можна пересуватися лише санами. Корабель, що опинився на замерзлій плитці не може рухатися поки не скресне крига. - Плитки, що повністю перебувають під роздільчою лінією Диску, вважаються розмерзлими – сани так само можуть пересуватися островами, а проходи між ними відкриті для судноплавства. Сани, що опинилися на водяній ділянці розмерзлої плитки, треба пересунути або на острівну частину, або на замерзлу. - Плитки, розділені лінією диску пополовині, вважаються замерзлими у верхній частині й розмерзлими в нижній. По верхній частині можуть пересуватися лише сани. Нижня частина, якщо це острів, придатна для пересування саней, або, якщо це вода, придатна для пересування кораблів. Якщо плитка, на якій перебуває корабель, після руху Диску Сонця виявляється розділеною пополовині, корабель пересувається на незамерзлу водяну частину плитки, якщо така є. Якщо після руху Диску Сонця сани не можна пересунути на землю або замерзлу частину тієї ж плитки, всі моряки, що перебувають у санах, втрачаються. ''2. Підготування до наступного раунду.'' - Всі задіяні моряки на особистих гральних полях переміщаються з "Відпочивальників" до "Готових", при цьому моряки не переходять з корабля на сани й навпаки. - Відмітники черговості ходу гравців пересуваються з другої доріжки визначення черговості ходу на першу. == '''ОПИС ДІЙ''' == '''Дія 1 – Взяти плитку''' Вартість: 1 моряк Гравець може вибрати:
а) взяти ОДНУ велику плитку з 4 доступних; б) взяти ОДНУ малу плитку з 6 доступних. Гравець бере вибрану плитку й кладе її перед сообою, утворюючи особистий запас. Особистий запас може складатися з будь-якої кількості плиток. '''Дія 2 – Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них''' Вартість: 2 моряки Гравець МУСИТЬ: 1 – Оновити великі плитки: гравець витягує 4 великих плитки й заміщує ними вже викладені великі плитки. Старі плитки повертаються до резерву. 2 – Взяти плитку: гравець бере велику або малу плитку Дослідження й кладе її до особистого запасу. Пунктирні лінії на плитці допомагають розміщувати їх на дошку; на рух вони не впливають. Корабель, що перебуває на плитці, має доступ до будь-якої її водної ділянки, не вкритої кригою, тому гравець може розмістити корабель у будь-якій частині цієї плитки. '''Дія 3 – Викласти плитку на гральну дошку''' Вартість: 1 моряк Гравець розміщує на гральній дошці ОДНУ плитку, що бере з особистого запасу, дотримуючись таких умов: - Плитка мусить вписуватися в пунктирну сітку гральної дошки. - Малі плитки Дослідження слід класти на дошку стороною Жослідження догори (з дідянками води й/або землі); великі плитки Дослідження можна класти будь-якою стороною. - Плитка Дослідження має бути викладена так, щоб принаймні однією своєю стороною торкатися або зображеної на полі плитки, або вже викладеної плитки, на якій перебуває корабель чи сани гравця. - Розміщуючи нову плитку стежте за тим, ощб межі суші й моря співпадали з межами уже викладених плиток. - Плитку не можна розмітити так, щоб заблокувати морський шлях з Гренландії до Північно-Західної Протоки. Якщо на щойно розміщеній плитці зображено спеціяльний символ, то на плитку одразу кладуть відповідний жетон. ''Жетони Мапування'' Острів повністю утворено, якщо ділянки хоча б двох дотичних плиток повністю оточені водою або обмежені краєм гральної дошки. Коли, розміщуючи плитку на дошці чи заповнюючи порожне місце, гравець утворює острів, то бере з режерву жетон "Мапування" і кладе собі на особисте гральне поле. Також він хдобуває стільки очок Престижу, скільки плиток утворюють цей острів. Якщо, розміщуючи плитку, гравець утворює декілька островів, він здобуває стільки жетонів "Мапування", скільки островів він утворив, і здобуває очки Престижу за кожен острів окремо. === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. 6de0be049742a73b7b67604f40f5d029a1998627 1537 1536 2015-05-04T21:01:08Z Savama 7567 Undo revision 1534 by [[Special:Contributions/Savama|Savama]] ([[User talk:Savama|talk]]) wikitext text/x-wiki == '''Північно-Західна Протока [Expedition Northwest Passage]''' == В 1845 році Сер Джон Франклін очолив експедицію організовану Британським Королівським флотом, з метою дослідити Північно-Західну протоку. Проте експедиція зникла. На пошуки відправились багато інших експедицій. Гравці, що виступають у ролі цих керівників, повинні вирушити в ризиковану подорож, щоб дізнатися про долю експедиції Франкліна та знайти й дослідити Північно-Західну протоку. == '''Мета гри''' == Гравець, що здобуває найбільше очок Престижу перемагає. У разі нічиєї, перемагає гравець, що перший повернувся до Гренландії. == '''Опис гри''' == На початку гри кожен гравець отримує: ''особисте гральне поле'', корабель (розміщується на стрілці Гренландія), сани (розміщуються на особистому гральному полі), 7 моряків. Гра триває 10 раундів. Кожен раунд складається з двох фаз: 1) ''Фаза дій'', коли гравці виконують доступні дії; 2) ''Фаза завершення раунду'', коли пересувається Диск Cонця й відбувається підготовка до наступного раунду. == '''Фаза дій''' == Гравець має 7 моряків, що їх можна використати для виконання таких дій: 1) Взяти плитку; 2) Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них; 3) Викласти плитку на гральну дошку; 4) Перевести моряків (з корабля на сани і навпаки); 5) Пересунути корабель або сани; 6) Дослідити; 7) Знайти; 8) Спасувати. На особистому гральному полі гравця є дві зони – "Корабель" та "Сани", що своєю чергою діляться на дві частини "Готові" та "Відпочивальники". Корабель чи Сани можуть виконувати будь-які дії, коли на них є матроси. На початку гри всі моряки перебувають на кораблі. Щойно гравець переводить їх на сани, як здобуває можливість пересувати їх по гральній дошці. Щоб виконати завдання гравець має використати потрібну кількість моряків. Щоб зазначити дію, гравець переміщає потрібну кількість моряків з "Готових" до "Відпочивальників" на кораблі чи на санах. Гравці виконують дії почергово, аж поки всі не спасують. Протягом ходу гравець: - МУСИТЬ виконати одну дію, використовуючи для цього потрібну кількість моряків. Якщо гравець не має "Готових" моряків, то він може лише спасувати. - Після виконання першої дії гравець може виконати одну або більше додаткових дій. Додаткові дії потребують участі на одного моряка більше, ніж зазвичай. == '''Фаза завершення раунду''' == ''1. Пересування Диску Сонця.'' Диск Сонця пересувається на одну позицію проти годинникової стрілки по Сонячній Арці. В основному, ігровий процес полягає в тому, що гравці почергово викладають на гральну дошку плитки "Дослідження". Залежно від раунду гри, гральна дошка може бути в тій чи іншій мірі "замерзлою". Розміщення Диску Сонця визначає, яка частина гральної дошки "замерзає", а яка "тане". - Плитки, що повністю перебувають над роздільчою лінією Диску, вважаються повністю замерзлими. Вода вкривається кригою, і по ній можна пересуватися лише санами. Корабель, що опинився на замерзлій плитці не може рухатися поки не скресне крига. - Плитки, що повністю перебувають під роздільчою лінією Диску, вважаються розмерзлими – сани так само можуть пересуватися островами, а проходи між ними відкриті для судноплавства. Сани, що опинилися на водяній ділянці розмерзлої плитки, треба пересунути або на острівну частину, або на замерзлу. - Плитки, розділені лінією диску пополовині, вважаються замерзлими у верхній частині й розмерзлими в нижній. По верхній частині можуть пересуватися лише сани. Нижня частина, якщо це острів, придатна для пересування саней, або, якщо це вода, придатна для пересування кораблів. Якщо плитка, на якій перебуває корабель, після руху Диску Сонця виявляється розділеною пополовині, корабель пересувається на незамерзлу водяну частину плитки, якщо така є. Якщо після руху Диску Сонця сани не можна пересунути на землю або замерзлу частину тієї ж плитки, всі моряки, що перебувають у санах, втрачаються. ''2. Підготування до наступного раунду.'' - Всі задіяні моряки на особистих гральних полях переміщаються з "Відпочивальників" до "Готових", при цьому моряки не переходять з корабля на сани й навпаки. - Відмітники черговості ходу гравців пересуваються з другої доріжки визначення черговості ходу на першу. == '''ОПИС ДІЙ''' == '''Дія 1 – Взяти плитку''' Вартість: 1 моряк Гравець може вибрати:
а) взяти ОДНУ велику плитку з 4 доступних; б) взяти ОДНУ малу плитку з 6 доступних. Гравець бере вибрану плитку й кладе її перед сообою, утворюючи особистий запас. Особистий запас може складатися з будь-якої кількості плиток. '''Дія 2 – Скинути викладені великі плитки Дослідження, витягнути нові, взяти одну з них''' Вартість: 2 моряки Гравець МУСИТЬ: 1 – Оновити великі плитки: гравець витягує 4 великих плитки й заміщує ними вже викладені великі плитки. Старі плитки повертаються до резерву. 2 – Взяти плитку: гравець бере велику або малу плитку Дослідження й кладе її до особистого запасу. Пунктирні лінії на плитці допомагають розміщувати їх на дошку; на рух вони не впливають. Корабель, що перебуває на плитці, має доступ до будь-якої її водної ділянки, не вкритої кригою, тому гравець може розмістити корабель у будь-якій частині цієї плитки. '''Дія 3 – Викласти плитку на гральну дошку''' Вартість: 1 моряк Гравець розміщує на гральній дошці ОДНУ плитку, що бере з особистого запасу, дотримуючись таких умов: - Плитка мусить вписуватися в пунктирну сітку гральної дошки. - Малі плитки Дослідження слід класти на дошку стороною Жослідження догори (з дідянками води й/або землі); великі плитки Дослідження можна класти будь-якою стороною. - Плитка Дослідження має бути викладена так, щоб принаймні однією своєю стороною торкатися або зображеної на полі плитки, або вже викладеної плитки, на якій перебуває корабель чи сани гравця. - Розміщуючи нову плитку стежте за тим, ощб межі суші й моря співпадали з межами уже викладених плиток. - Плитку не можна розмітити так, щоб заблокувати морський шлях з Гренландії до Північно-Західної Протоки. Якщо на щойно розміщеній плитці зображено спеціяльний символ, то на плитку одразу кладуть відповідний жетон. ''Жетони Мапування'' Острів повністю утворено, якщо ділянки хоча б двох дотичних плиток повністю оточені водою або обмежені краєм гральної дошки. Коли, розміщуючи плитку на дошці чи заповнюючи порожне місце, гравець утворює острів, то бере з режерву жетон "Мапування" і кладе собі на особисте гральне поле. Також він хдобуває стільки очок Престижу, скільки плиток утворюють цей острів. Якщо, розміщуючи плитку, гравець утворює декілька островів, він здобуває стільки жетонів "Мапування", скільки островів він утворив, і здобуває очки Престижу за кожен острів окремо. === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. 27088732feb19cc7b8adef78ffbdaf1354071991 1538 1537 2015-05-04T21:02:36Z Savama 7567 wikitext text/x-wiki '''''Looking for the Franklin Expedition''''' ''In 1845, Sir John Franklin led an expedition on behalf of the British Royal Navy to find and explore the last portion of the Northwest Passage. They sailed into unknown waters, and no-one ever heard from them again... Players must venture into these hazardous Arctic waters in order to discover Franklin’s fate and succeed where he failed: by finding the Northwest Passage.'' ---- In the game, prestige is awarded for exploring islands and straits, getting information from Inuits or Cairns about the Franklin Expedition, finding shipwrecks of the expedition, and for being among the first to find their way up to the Northwest Passage and back to Groenland. The player with the most Prestige points at the end of the game is the winner. In case of a tie, the first tied player to have returned to Greenland is the winner. == GAME CYCLE == The game is divided into ten rounds. At the end of each round, the solar disc moves, and part of the board above the sun freezes into ice or melts back to sea. During one round, player will take up to 7 actions, in turn. Actions can be taken either from the ship, using crewmen on the ship, or from the sled, using crewmen on the sled. During one turn, one player can play one or more actions. However, '''all additional actions (beyond the first one) will cost one more crewman than normal'''. In order to stop playing more actions during one turn, click the blinking [End Turn] at the top of the screen. At the end of the round, all used Crewmen move back to «Available». The next turn order is the order in which players used their last crewmen (or passed). This is shown by the turn order markers at the top left of the board. == ACTIONS == === Draw a tile === ''Cost: 1 Crewman'' <Click on the chosen tile at the top of the board.> <br/> === Refresh tiles and Draw === ''Cost: 2 Crewmen'' <Click on the "Renew deck" icon.> The player MUST: # Refresh: all large tiles available on the board are replaced with four new tiles which are randomly drawn from the reserve. The replaced tiles are placed back into the reserve. # Draw a tile: he takes either a large or a small Exploration tile and adds it to his personal reserve. <br/> === Place a tile === ''Cost: 1 Crewman'' <Click on the tile from your hand, rotate it or flip it as fit, and click on the white marker on the board.> The player places one tile on the board, which is taken from his personal reserve. He must meet the following conditions: * The tile  must  be placed in line with the black grid on the board. * The tile  must  be placed so that  at  least  one  side (long or large) must be flush with a tile on which the player has a presence (Ship or Sled, depending on which one executes this action). * The land and sea areas of the newly-placed tile must correspond with all land and  sea tiles of adjacent tiles (both orthogonally and diagonally). If, by placing a tile, a player creates a space the size of a small Exploration tile which is surrounded on all sides by tiles, a matching small Exploration tile is taken from the reserve and placed to fill the empty space. An island is complete when the land areas of at least two tiles are completely surrounded by water or the edge of the board. In case a player completes one or several islands, he gets one Cartography token, and Prestige points according to the size of the island. <br/> === Transfer Crew === ''Cost: 1 Crewman'' <Click on the back arrows on the player board> Crewmen are moved from/to the ship/sled, thus deploying or taking back the sled into the ship. Taking back crewmen in the ship can only happen if the sled and ship are on the same tile. Both active and resting crewmen can be transferred. <br/> === Movement === ''Cost: 1 Crewman'' <Click on the ship or sled, then on its destination.> '''Ship Movement''': The player moves his ship onto one adjacent tile linked to the tile it currently occupies by a sea passage. '''Sled Movement''': The player moves his sled onto one adjacent tile linked to the one it currently occupies by a land passage. The Sled cannot cross the sea unless it is frozen. Multiple Ships and Sleds can be on the same tile. A frozen tile is unreachable for a ship. If a ship, due to a season change, finds itself in frozen waters, the ship is blocked in and will not be able to move until the thaw. A frozen tile is considered to be entirely composed of land, so a Sled can move freely on it. <br/> === Explore a Franklin site or a Strait === ''Cost: 3 Crewmen'' <Click on the bonus chip.> 1 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3), and additionally, points are awarded at the end of the game for the players having the most bonuses of a given type (see tooltip). <br/> === Discover an Inuit or a Cairn === ''Cost: 2 Crewmen'' <Click on the bonus chip.> 2 prestige point is awarded for the discovery multiplied by the zone multiplier (x1 / x2 / x3). <br/> === Pass === A player can choose to Pass and take no action during his turn, even if he still has available Crewmen. In this case, the player cannot take any more actions during this round. If a player has no available Crewmen, he automatically passes. == END OF THE GAME == The game ends either: at the end of the Action Phase of the tenth round or if all of the Expeditions have returned to Greenland. In addition to the point earned during the game, players receive more Prestige points based on the tokens they picked up along the way. ==== Exploration Points: ==== Point are awarded to the player(s) with the most, second most, and third most Shipwrecks, Straits, and Cartography tokens (see tooltips for scoring). ==== Set Points: ==== Each set is composed of one token of each Discovery type – one Inuit, one Cairn, one Shipwreck, one Strait, and one Cartography token. Each set gives a bonus of 6 prestige points. ==== Abandonment Penalty: ==== Each Sled and/or Ship which did not return to Greenland before the end of the tenth Exploration season is lost. When a Ship or a Sled is lost, all of the crewmen in the corresponding column are lost with it. Every lost Ship and/or Sled gives a penalty of -2 Prestige points for each corresponding lost Crewman. An abandoned ship gives a penalty of -2 Prestige points. b1ae8800a8556d2ec55b52cf4109d6778adb2b76 Rating 0 16 1539 1379 2015-05-05T15:16:37Z Sourisdudesert 1 /* Okay, but I want to know the formula! */ wikitext text/x-wiki [[Category:Help]] == What is an Elo rating? == Your Elo rating for a game is an indicator of your level of skill at that game. It's a 4 digit number followed by the symbol http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you've never played a game on BGA, your initial rating will be 1500. Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game? == The number of Elo points gained or lost in a game depends on (1) the Elo rating of your opponents, and (2) what place you achieve in the game (i.e. 1st place, 2nd place). For example: * If you end the game in a better position than a player with a higher Elo, you gain a lot of points. * If you end the game in a better position than a player with a lower Elo, you gain fewer points. * If you end the game in a worse position than a player with a lower Elo, you lose a lot points. * And so on... == Some advice == * There's little to be gained by beating players with an Elo rating a lot lower than yours. Try to find opponents with a similar Elo rating to yourself: it's both more fun and better for your Elo. * What place you achieve in a game is very important when calculating the Elo. This is why it is important to continue fighting for minor places in the game even if you think you can't win. * The number of Elo points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you lose as many points as if you had finished the game in last place, plus an additional penalty of 10 points. Even if you are in a difficult situation it is in your interest to play the game until the end - or concede the victory to your opponent. == How is my Elo rating computed? == The BGA Elo system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system Elo rating system] in use for chess. The Elo system's main principle is the following: the Elo points difference between 2 players determines the probability of each of them winning an encounter. If two players have the same Elo, they have an equal (50/50) probability of winning. If one player has 400 more points than the other, his probability of winning is 90%. Elo points gains and losses will, over time, tend to adjust the Elo rating of each player to reflect the actual probability that either of them will win a particular encounter. Some changes have been made to the Elo system used on BGA: * During your first 30 games, your Elo rating is more "elastic": you can win (or lose) more points in each game. This way, your Elo rating converges faster to you "natural" rating. * The original Elo rating system was designed for 2 player games. For games with more than 2 players, BGA considers (for the Elo rating) that you win a 2-player game against each opponent who placed below you, and that you lose a 2-player game against each who place above you. * Games with more than 2 players last longer. For this reason, there are more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula! == The formula is exactly the one used by the Elo rating system, with the following adjustments: * First of all, if someone leaves a game for any reason this game is not taken into account by the Elo rating system. * K=60 for the first 30 games, K=40 afterwards. * K is multiplied by (N/2) for N-player games. If N exceeds the "advised number of players" for this game, K is multiplied by (A/2), where A is the "advised number of players". == Beginners, Average players, Good players, Experts, Masters == * Beginner: Everyone starts as a Beginner. You stay a Beginner until you achieve a victory, regardless of your Elo. If you have at least 1 victory, the following levels apply, depending on your Elo: * Average: < 1600 * Good: >= 1600 * Expert: >= 1800 * Master: >= 2000 a42d5f4d1cf5860a4865f894fd2fa8dc85a300b6 Tutorial reversi 0 57 1540 1369 2015-05-09T20:00:48Z Wucnuc 8500 wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for white and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('img/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just call "this.addTokenOnBoard( 2, 2, <your_player_id> )" in your "setup" Javascript method, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "states.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where she is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where she is allowed to play. This method will be used in particular: * As we just said, to help the player to see where she can play. * When the player plays, to check if she has the right to play here. This is pure PHP programming here, and there are no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight the squares where the player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on the server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in stats.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 6a1bd5ebb9cb9f97b76884d470d77795e391c7fc Gamehelptournay 0 143 1541 1353 2015-05-11T00:45:32Z Senatorhung 4176 /* Details of prestige buildings */ wikitext text/x-wiki Thanks to Mark Johnson (Eeeville) for his Tournay card descriptions used in the BGA adaptation! The '''game ends''' when both of the following conditions are met, or if condition 1 is met by more than one player:<BR> <OL><LI>A player has filled 9 spaces with at least 2 visible prestige buildings.</LI> <LI> One Town Crier card more than the number of players has been revealed.</LI></OL> The last round is triggered at the beginning of the start player's turn and each player gets a normal turn in this round. Then all players can choose a final card to play into their districts. ===Details of prestige buildings=== * You cannot score more than 12 victory points from the same prestige building. * If two players build the same prestige building there is only a single scoring. '''Yellow:''' *'''Belfry''': per set (1 yellow + 1 white + 1 red) of buildings or characters *'''City Hall''': per yellow citizen (2x) *'''Cloth Hall''': per yellow building or character (2x) *'''Mint''': per set of 4 deniers (2x) *'''Tour des Six''': per character (2x) '''White:''' *'''Cathedral''': only the player who builds it earns 8 PPs. *'''La Madeleine''': per prestige building (2x) *'''Saint-Brice''': per set (1 yellow + 1 white + 1 red) of buildings or characters *'''Saint-Jacques''': per white building or character (2x) *'''Saint-Nicolas''': per set of citizens you own (1 yellow +1 white +1 red) *'''Saint-Quentin''': per white citizen (2x) '''Red:''' *'''Pont des Trous''': per set (1 yellow + 1 white + 1 red) of citizens *'''Porte de la Vigne''': per red citizen (2x) *'''Tour d’Arras''': per white and yellow building (2x) *'''Tour Henry VIII''': per rampart built (2x) *'''Tour Saint-Georges''': per red card building or character (2x) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="110" | Prestige Building ! align="center" width="50" | Colour ! align="center" width="20" | # ! align="center" width="50" | Cost to Play ! align="center" width="50" | Builder Points ! align="center" width="50" | Non-Builder Points ! align="center" width="225" | Condition |- | align="center" | '''Belfry''' | align="center" | Yellow | align="center" | 1 | align="center" | 5 deniers | align="center" | 4 | align="center" | 2 | align="center" | each set of visible buildings or characters<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''City Hall''' | align="center" | Yellow | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each yellow citizen owned |- | align="center" | '''Cloth Hall''' | align="center" | Yellow | align="center" | 2 | align="center" | 1 yellow citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible yellow building or character |- | align="center" | '''Mint''' | align="center" | Yellow | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each set of 4 deniers |- | align="center" | '''Tour des Six''' | align="center" | Yellow | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each visible character |- | align="center" | '''Cathedral''' | align="center" | White | align="center" | 1 | align="center" | 20 deniers | align="center" | 8 | align="center" | 0 | align="center" | none |- | align="center" | '''La Madeleine''' | align="center" | White | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each visible prestige building |- | align="center" | '''Saint-Brice''' | align="center" | White | align="center" | 1 | align="center" | 5 deniers | align="center" | 4 | align="center" | 2 | align="center" | each set of visible buildings or characters<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Saint-Jacques''' | align="center" | White | align="center" | 2 | align="center" | 1 white citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible white building or character |- | align="center" | '''Saint-Nicolas''' | align="center" | White | align="center" | 1 | align="center" | 5 deniers | align="center" | 3 | align="center" | 1 | align="center" | each set of citizens you own<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Saint-Quentin''' | align="center" | White | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each white citizen owned |- | align="center" | '''Pont des Trous''' | align="center" | Red | align="center" | 1 | align="center" | 5 deniers | align="center" | 3 | align="center" | 1 | align="center" | each set of citizens you own<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Porte de la Vigne''' | align="center" | Red | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each red citizen owned |- | align="center" | '''Tour d’Arras''' | align="center" | Red | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each visible white and yellow building |- | align="center" | '''Tour Henry VIII''' | align="center" | Red | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each rampart card built |- | align="center" | '''Tour Saint-Georges''' | align="center" | Red | align="center" | 2 | align="center" | 1 red citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible red building or character |} 6e135114d15c43b6a515c44485cf9197c678e343 Tutorial gomoku 0 73 1542 939 2015-05-11T02:34:34Z Wucnuc 8500 getFormattedCoordinates is undefined wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created: [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( 'img/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * In .js->setup() assign the constants to this variable this.gameConstants = gamedatas.constants; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone on ${coord_x},${coord_y}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { // At the end of the slide, update the intersection dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'no_stone' ); dojo.addClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'stone_' + notif.args.color ); dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); // We can now destroy the stone since it is now visible through the change in style of the intersection dojo.destroy( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ); })); slide.play(); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( 'img/stones.png'); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, send a score update notification to the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 25040dd1058c4a62b2b3906a15f875ce75adeac6 1543 1542 2015-05-11T02:41:43Z Wucnuc 8500 .gmk_intersection also requires the stones background image wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created: [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( 'img/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * In .js->setup() assign the constants to this variable this.gameConstants = gamedatas.constants; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone on ${coord_x},${coord_y}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { // At the end of the slide, update the intersection dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'no_stone' ); dojo.addClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'stone_' + notif.args.color ); dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); // We can now destroy the stone since it is now visible through the change in style of the intersection dojo.destroy( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ); })); slide.play(); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-image: url( 'img/stones.png' ); } .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( 'img/stones.png' ); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(): * modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); * and at the end of the setup make the black player active <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, send a score update notification to the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 15b98bb1149a92053c70a0eb31c694706bc1c4a5 1544 1543 2015-05-11T02:53:22Z Wucnuc 8500 Moved modifying default player colors to the previous section wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created: [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( 'img/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * In .js->setup() assign the constants to this variable this.gameConstants = gamedatas.constants; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone on ${coord_x},${coord_y}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { // At the end of the slide, update the intersection dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'no_stone' ); dojo.addClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'stone_' + notif.args.color ); dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); // We can now destroy the stone since it is now visible through the change in style of the intersection dojo.destroy( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ); })); slide.play(); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-image: url( 'img/stones.png' ); } .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( 'img/stones.png' ); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(), at the end of the setup make the black player active: <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, send a score update notification to the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] a2366f7429b8cb00f4379fa40f09f5deebc771f4 1545 1544 2015-05-11T02:53:33Z Wucnuc 8500 Moved modifying default player colors to this section wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'emtpy game' template == Here is how your games looks by default when it has just been created: [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( 'img/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * In .js->setup() assign the constants to this variable this.gameConstants = gamedatas.constants; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone on ${coord_x},${coord_y}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { // At the end of the slide, update the intersection dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'no_stone' ); dojo.addClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'stone_' + notif.args.color ); dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); // We can now destroy the stone since it is now visible through the change in style of the intersection dojo.destroy( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ); })); slide.play(); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-image: url( 'img/stones.png' ); } .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( 'img/stones.png' ); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> Finally, make sure to modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(), at the end of the setup make the black player active: <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, send a score update notification to the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] ceb8a87083f2fa4459dd5c58d091b907c9ef6a7f Gamehelptargi 0 169 1546 1406 2015-05-13T18:52:14Z Saubohne5000 8740 wikitext text/x-wiki Each round of play has the following stages: # Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column as your opponent's Targi. # Place 1 or 2 "tribal markers" in the middle of the game board at the intersection of the rows/columns of your targi. # You may then activate the cards under each of your pieces. These cards may give you more goods, or they may let you spend your goods to purchase special cards to place in your personal tableau. You may only hold 3 gold and 10 goods total between rounds. The game ends when a player has filled their tableau, or when the robber has completed one jog around the map. In addition to the victory points earned during the game and from special card abilities, you also get: * 4 victory points for a building a row of identical cards in your tableau, and * 2 victory points for a row of all different cards - Mit dem Händler ist mehrfach der Tausch von drei gleichen Waren in eine Goldmünze oder von zwei gleichen in eine andere Ware möglich. - Mit der Fata Morgana darf ein Schnittpunktmarker auf eine andere ungenutzte Karte im Mittelfeld gesetzt werden. - Der Silberschmied wandelt Waren oder Gold in Siegpunkte um. - Die Karawane liefert Rohstoffe entsprechend der obersten verdeckten Warenkarte. - Mit der Stammeserweiterung kann die obersten Stammeskarte vom Stapel verworfen werden. afc35eb52422684cff2ad441bf04d9d57df882b1 Gamehelpyatzy 0 122 1547 1380 2015-05-17T07:41:28Z Electricblue 8908 Bonus for subsequent Yahtzees not in the current version on BGA, so removed from these rules. wikitext text/x-wiki The game Yahtzee consists of 13 rounds. In each round, you roll 5 dice and then score the roll in a different category of your choice. During a round, you can roll the dice up to three times before scoring -- the initial roll (in which you must roll all the dice), plus two optional re-rolls of any or all dice. There are 13 scoring categories, and each must be used for one of the 13 rounds. This often results in a zero score for some categories. The 13 scoring categories are as follows: 1-6: There is one category for each number on the die. In these categories, the score is the sum of the pips on the dice of that number. For example, a roll of 1-1-2-5-5 could be scored as 2 points in the "ones" category, 2 points in the "twos" category, 10 points in the "fives" category, or 0 points in the "threes," "fours," or "sixes." If a player scores a total of at least 63 points across these six boxes, a bonus of 35 points is added. 7. Three-Of-A-Kind: At least three dice showing the same face -- Points equal the sum of all 5 dice (not just the 3 of a kind) 8. Four-Of-A-Kind: At least four dice showing the same face -- Points equal the sum of all 5 dice (not just the 4 of a kind) 9. Full House: A three-of-a-kind and a pair -- 25 points 10. Small Straight: Four sequential dice 1-2-3-4, 2-3-4-5, or 3-4-5-6) -- 30 points 11. Large Straight: Five sequential dice (1-2-3-4-5 or 2-3-4-5-6) -- 40 points 12. Yahtzee: All five dice showing the same face -- 50 points 13. Chance: Any combination -- points equal the sum of all 5 dice 14. Rigole: 4 times the same number and 1 time the opposite number on a dice (Ex. 1-1-1-1-6, 2-2-2-2-5, 3-3-3-3-4, 4-4-4-4-3, 5-5-5-5-2, 6-6-6-6-1) e9a348b7d4bc58b4c56bd31dfc6c2f9b0278de11 Main game logic: yourgamename.game.php 0 86 1548 1199 2015-05-17T23:52:12Z Wucnuc 8500 Removed duplication wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 89 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. Notifications sent between the game start (setupNewGame) and the end of the "action" method of the first active state will never reach their destination. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array. Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. d767eb6cad16b82ab3a33d3d78f39bd74f26b6e4 1549 1548 2015-05-18T20:10:03Z Chaf 8916 /* Use globals */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 79 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. Notifications sent between the game start (setupNewGame) and the end of the "action" method of the first active state will never reach their destination. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array. Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. 84fef5cdb97d4d2f5e8738823794bb83b39f232b Gamehelpsobek 0 166 1550 1416 2015-05-27T23:56:49Z Squarerootofthree 5668 Undo revision 1415 by [[Special:Contributions/340427770|340427770]] ([[User talk:340427770|talk]]) wikitext text/x-wiki ==遊戲簡介== 遊戲簡介】供奉索貝克神廟的工程已經如火如荼的建造當中。一個全面的經濟體系已在施工現場旁成立:有一個新的市場,並且有帆船在尼羅河上下航行,不斷帶來各種商品。商家之間的競爭自然激烈,有些商家為了累計更多的榮耀和財富已經開始變得腐敗。主要的財富,其實您也是屬於當地商人的行會,並準備盡全力代價打敗你的對手... 在3輪中比你的對手獲得更多的錢,但盡量不要太腐敗! 玩家流程】一開始綠色牌背的卡每個人發兩張。 輪到你的時候,有以下三擇一選項: 1.拿一張卡(從岸邊選一個停靠的船) 2.出一張人物卡(使用卡片上的功能,或者當棄牌使用) 3.打一組牌(三個一樣為一組) 你的回合結束之後就換你左邊的玩家進行挑選三個行動,然後再換下一家,依此類推。 結束】當牌堆被拿完,第一輪結束,遊戲將進行三輪。 打出來的牌上面會有分數計算,分數高的為優勝。 心得】此款遊戲設計者也設計了其它多款有名的遊戲,像圓桌武士、Mr.Jack,牙買加,群島爭霸...等。這一款遊戲也算是小品遊戲,但中間不乏有策略、運氣成分。 玩起來節奏也快,不會拖臺錢,算是CP值很高的遊戲。 另外一個值得推薦的地方就是它的美工設計,連內盒都設計很漂亮,真是個好遊戲! 卡牌屋全彩規則也為大家準備好了,讓你輕鬆上手沒煩惱。 == 卡牌与人物牌介绍 == 守卫x4:你的计分标记马上前进到下一个该符号的地方,并且选择一个对手,他的计分标记后退到前一个该符号的地方。(这四个事件在游戏二、三轮比较强力,各只有1个)。 繁殖x2:选择你一个在场的牛、鱼、小麦组合,放置该标记,该组合这轮结束多两个甲虫。 绿洲x2:额外奖励一个行动(送一个回合,马上执行)。(中规中矩) 诈骗x1:在你的黑锅里有多少张牌,马上加多少分。(表面没啥用,其实。。。) 诅咒x2:把该标志送给一个对手,在计算爆锅的时候,他的黑锅算多有两张牌。 复活x1:马上把你黑锅里的所有卡牌加入手牌。(游戏后期最强事件,要啥有啥…) ==Character cards== * 1 x Queen Sobek Neferou - draw 3 cards and add them to your hand. * 2 x High Priest/Priestess - discard all the cards of one goods type from your corruption pile. Characters of that goods type can be discarded. Amulets (wild cards) cannot be discarded. * 2 x Scribe - your opponents reduce their hands down to 6 cards; the remainder are added to their corruption pile. * 1 x Vizir - add a card of your choice to your hand from an opponent's corruption pile. * 1 x Courtesan - add 1 or 2 cards from your hand to an existing played set. * 1 x Thief - steal a card from an opponent. You can see the different coloured backs of the card so you know which type of card you are stealing. 货物卡 There are in总:54货物卡 6×象牙 7×乌木 7×大理石 9×牛 10×鱼 10×小麦 5×护身符 Nine of the cards have a different coloured back; the player's starting hand is dealt from these leaving 45 cards which are shuffled with the character cards to form the deck. In a two player game 9 cards are removed at random so there will be only 5 goods deliveries not 6 as normal. ==End of the round== The round ends and is scored when the last card is taken from the marketplace. Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand. You cannot play character cards; you cannot add to existing sets. All cards remaining in the players hand are added to their corruption pile. Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs. Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols. == Game end == The game ends after 3 rounds. The game can end early if one player gets more than 100 points. d591dc86c418c228091aefa52e80bfe0bd10187a 1551 1550 2015-05-27T23:58:39Z Squarerootofthree 5668 wikitext text/x-wiki ==Theme== Players are merchants trading in the economy that has grown up next to the construction site of the temple dedicated to Sobek. There's a market, and the feluccas sailing up and down the Nile are bringing goods of all sorts. You have 3 rounds in which to acquire more money than your rivals, but try not to become too corrupt. ==Game turns and actions== On your turn you must choose one of the 3 actions. Then play passes to the player on your left. The actions are: * '''Take a card from the marketplace and add it to your hand''' : Only the first four cards (starting from the left) are available. Taking the first available card has no consequences since the order of arrival of the feluccas is respected. However, taking one of the other cards causes corruption. All the cards that you skip end up in your corruption pile. * '''Play a character card and apply its power''' : See below for powers. * '''Play a set''' : A set is a group of at least three goods cards of the same type. A set can include one or more amulets which act as wild cards (jokers). A set can also include characters - each character is associated with a goods type; this is shown on the card. When a character is played as part of a set, its power is ignored. : It is possible to add cards to a set that has already been played (in order to earn more points during scoring), but the same rule still applies: you must add a minimum of 3 new cards. : When a set is played an event are triggered (provided at least 1 of the 5 event tokens remains). The player who played the set chooses an event from the remaining tokens and immediately applies its effect. The token is then discarded. ==Event tokens== There are 12 event tokens with 5 randomly selected for each round: * 4 x Guild - (one of each of snake, reed, ankh, scorpion). On the scoring track, move your scoring marker forward to the next space of that symbol and move an opponent's scoring marker back to the next space of that symbol. * 2 x Flood - Take another turn * 2 x Curse - Add a curse token to another player's corruption pile; it counts as 2 cards in that player's pile. * 2 x Prosperity - add the token to one of your fish, cattle or wheat sets, thus increasing the score of this set. * 1 x Embalming - return all the cards from your corruption pile to your hand * 1 x Deceit - Score the number of cards in your corruption pile ==Character cards== * 1 x Queen Sobek Neferou - draw 3 cards and add them to your hand. * 2 x High Priest/Priestess - discard all the cards of one goods type from your corruption pile. Characters of that goods type can be discarded. Amulets (wild cards) cannot be discarded. * 2 x Scribe - your opponents reduce their hands down to 6 cards; the remainder are added to their corruption pile. * 1 x Vizir - add a card of your choice to your hand from an opponent's corruption pile. * 1 x Courtesan - add 1 or 2 cards from your hand to an existing played set. * 1 x Thief - steal a card from an opponent. You can see the different coloured backs of the card so you know which type of card you are stealing. ==Goods cards== There are 54 goods cards in total: :6 x Ivory :7 x Ebony :7 x Marble :9 x Cattle :10 x Fish :10 x Wheat :5 x Amulet Nine of the cards have a different coloured back; the player's starting hand is dealt from these leaving 45 cards which are shuffled with the character cards to form the deck. In a two player game 9 cards are removed at random so there will be only 5 goods deliveries not 6 as normal. ==End of the round== The round ends and is scored when the last card is taken from the marketplace. Each player may play ''horizontal'' sets from their hand. These do not score as highly as sets played in the round proper but they do reduce the number of cards in the hand. You cannot play character cards; you cannot add to existing sets. All cards remaining in the players hand are added to their corruption pile. Sets are scored by multiplying the number of scarabs in the set by the number of cards in the set (including amulets, characters and Prosperity tokens). Horizontal sets are scored by adding scarabs. Then the '''corruption penalty''' is applied. The player with the most cards in their corruption pile (including Curse tokens) is the most corrupt. In the event of a tie the player with the most scarabs. If there is still a tie then all players receive the penalty. The size of the corruption penalty depends on the amount of points earned by the player through scoring sets. For every 10 points earned through sets the player will move back to the next symbol of the type they ended up on. For example if Kate earned 23 points and ended up on the Ankh symbol then this is 2 "lots" of ten and so she will move back 2 Ankh symbols. == Game end == The game ends after 3 rounds. The game can end early if one player gets more than 100 points. 30e7c1e67b298ba7b4c34925c31df0ad74a8049e Kaozeal:Gamehelpcarrara 1 194 1552 2015-05-29T21:55:30Z Retourdecrem 9003 Created page with " Présentation du jeu et de son matériel 1. placez le plateau de jeu et plateau des objectifs au centre de la table. 2. Chaque joueur [pdf regles tronqué] 7. les 36 objets..." wikitext text/x-wiki Présentation du jeu et de son matériel 1. placez le plateau de jeu et plateau des objectifs au centre de la table. 2. Chaque joueur [pdf regles tronqué] 7. les 36 objets sont regroupés en 6 catégories. Prenez un objet de chacune des 6 catégories et placez le à l'emplacement dédié aux objets sur le plateau (6 objets au total se trouveront sur cet emplacemennt). Les 5 objets restants de chaque catégories sont placés par catégorie sur le côté du plateau. 8. Chaque joueur prend les marqueurs de score de la couleur de son choix, et les place devant lui. Puis il en choisit un, qu'il dépose sur la case 0 du plateau de score. 9. les marqueurs des points sont placés sur le coté du plateau. 6b6cf6cadfde0ab481d947d868cb19009d2d371c 1553 1552 2015-05-29T21:56:02Z Retourdecrem 9003 wikitext text/x-wiki ''' == Présentation du jeu et de son matériel''' == 1. placez le plateau de jeu et plateau des objectifs au centre de la table. 2. Chaque joueur [pdf regles tronqué] 7. les 36 objets sont regroupés en 6 catégories. Prenez un objet de chacune des 6 catégories et placez le à l'emplacement dédié aux objets sur le plateau (6 objets au total se trouveront sur cet emplacemennt). Les 5 objets restants de chaque catégories sont placés par catégorie sur le côté du plateau. 8. Chaque joueur prend les marqueurs de score de la couleur de son choix, et les place devant lui. Puis il en choisit un, qu'il dépose sur la case 0 du plateau de score. 9. les marqueurs des points sont placés sur le coté du plateau. 71115a993a1fdfc6a54c9b993cc2e74521ab4420 1554 1553 2015-05-29T21:56:44Z Retourdecrem 9003 wikitext text/x-wiki ''' == Présentation du jeu et de son matériel''' == 1. Placez au centre de la table le plateau de jeu et plateau des objectifs. 2. Chaque joueur [pdf des regles est tronqué] 7. les 36 objets sont regroupés en 6 catégories. Prenez un objet de chacune des 6 catégories et placez le à l'emplacement dédié aux objets sur le plateau (6 objets au total se trouveront sur cet emplacemennt). Les 5 objets restants de chaque catégories sont placés par catégorie sur le côté du plateau. 8. Chaque joueur prend les marqueurs de score de la couleur de son choix, et les place devant lui. Puis il en choisit un, qu'il dépose sur la case 0 du plateau de score. 9. les marqueurs des points sont placés sur le coté du plateau. f18b0d75f23b3878148adcb0d362c835bfb544ed Help 0 4 1555 1486 2015-06-02T07:22:49Z Januszk0 3262 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] is the most complete source of help for BGA. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this wil direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcheckers|Checkers]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpeightmastersrevenge|8 Master's Revenge]] * [[Gamehelpelfenland|Elfenland]] </td> <td valign="top"> * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpinjawara|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] </td> <td valign="top"> * [[Gamehelpkoryo|Koryŏ]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsechsnimmt|6 Nimmt!]] </td> <td valign="top"> * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelpsechsnimmt|Take 5!]] * [[Gamehelptashkalar|Tash-Kalar]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] </td> <td valign="top"> * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> 0995ca56598fd11e793f09fc6ee1970b0d9a2dd0 1556 1555 2015-06-02T07:26:24Z Januszk0 3262 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] is the most complete source of help for BGA. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Referral|Referral]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcheckers|Checkers]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpeightmastersrevenge|8 Master's Revenge]] * [[Gamehelpelfenland|Elfenland]] </td> <td valign="top"> * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpinjawara|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] </td> <td valign="top"> * [[Gamehelpkoryo|Koryŏ]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsechsnimmt|6 Nimmt!]] </td> <td valign="top"> * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelpsechsnimmt|Take 5!]] * [[Gamehelptashkalar|Tash-Kalar]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] </td> <td valign="top"> * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> 6b550d20d077260f43b50db9612646f5e4dcd596 1557 1556 2015-06-02T09:22:17Z Januszk0 3262 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] is the most complete source of help for BGA. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcheckers|Checkers]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpeightmastersrevenge|8 Master's Revenge]] * [[Gamehelpelfenland|Elfenland]] </td> <td valign="top"> * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpinjawara|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] </td> <td valign="top"> * [[Gamehelpkoryo|Koryŏ]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsechsnimmt|6 Nimmt!]] </td> <td valign="top"> * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelpsechsnimmt|Take 5!]] * [[Gamehelptashkalar|Tash-Kalar]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] </td> <td valign="top"> * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> 6b2838d85104f3f99d51729f7db2d82fc559dd6f 1558 1557 2015-06-02T10:01:49Z Januszk0 3262 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] is the most complete source of help for BGA. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpsechsnimmt|6 Nimmt!]] * [[Gamehelpeightmastersrevenge|8 Master's Revenge]] * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcheckers|Checkers]] * [[Gamehelpchess|Chess]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] </td> <td valign="top"> * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpelfenland|Elfenland]] * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpflorenzacardgame|Florenza: The Card Game]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphanabi|Hanabi]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] </td> <td valign="top"> * [[Gamehelpinjawara|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpk2|K2]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] * [[Gamehelpkoryo|Koryŏ]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppolis|Polis: Fight for the Hegemony]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] </td> <td valign="top"> * [[Gamehelpquantum|Quantum]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelptashkalar|Tash-Kalar]] * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] </td> <td valign="top"> * [[Gamehelpcarrara|The Palaces of Carrara]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> 7063fd96aa10b05672e83da1bddbb66166bb42e6 1559 1558 2015-06-02T10:07:22Z Januszk0 3262 wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] is the most complete source of help for BGA. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpsechsnimmt|6 Nimmt!]] * [[Gamehelpeightmastersrevenge|8 Master's Revenge]] * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpassyria|Assyria]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcheckers|Checkers]] * [[Gamehelpchess|Chess]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpelfenland|Elfenland]] * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpflorenzacardgame|Florenza: The Card Game]] </td> <td valign="top"> * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphanabi|Hanabi]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpinjawara|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpk2|K2]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] * [[Gamehelpkoryo|Koryŏ]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpneutreeko|Neutreeko]] </td> <td valign="top"> * [[Gamehelpniagara|Niagara]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppolis|Polis: Fight for the Hegemony]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquantum|Quantum]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelptashkalar|Tash-Kalar]] * [[Gamehelptheboss|The Boss]] </td> <td valign="top"> * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpcarrara|The Palaces of Carrara]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> aafcedce6b865af54fdb175dbde10141fb8d8ca4 Css Customization 0 195 1560 2015-06-17T08:02:06Z Sourisdudesert 1 Created page with " This feature allows you to customize Board Game Arena with some CSS. TODO" wikitext text/x-wiki This feature allows you to customize Board Game Arena with some CSS. TODO 682e83c5a59fc6235b74229b26758baedb7fff12 1561 1560 2015-06-17T15:46:12Z Sourisdudesert 1 wikitext text/x-wiki This feature allows you to customize Board Game Arena with some CSS. = Why this feature? = At first, because this is cool :) Then, a lot of players told us that BGA should look better, and we constantly tried to make it look much better. But as it is a community-based website, we found out that we should allow YOU to participate. So this is why you can customize BGA appearance and share your customization with others. = How it works? = From your account preferences, "advanced" tab, you can write some CSS. As soon as you click on "save", it is integrated to BGA CSS for your account. = What is CSS ? = Well... if you don't know what CSS is, sorry but you shouldn't try to customize BGA appearance with this tool. = Troubleshooting = == The CSS code I wrote is not taken into account == At first, check the sourcecode of the BGA page. If your CSS code does not appear there, then the most probable reason is that you did a syntax error in your CSS code, so we didn't take a part of your code into account. If it appears, then it should be an error in one of your declaration (ex: wrong #id). fb2117fe90c64c13fa8ae5d4386a5fa40dccf1fb 1562 1561 2015-06-17T15:52:42Z Sourisdudesert 1 wikitext text/x-wiki This feature allows you to customize Board Game Arena with some CSS. = Why this feature? = At first, because this is cool :) Then, a lot of players told us that BGA should look better, and we constantly tried to make it look much better. But as it is a community-based website, we found out that we should allow YOU to participate. So this is why you can customize BGA appearance and share your customization with others. = How it works? = From your account preferences, "advanced" tab, you can write some CSS. As soon as you click on "save", it is integrated to BGA CSS for your account. = What is CSS ? = Well... if you don't know what CSS is, sorry but you shouldn't try to customize BGA appearance with this tool. = Reset CSS = Just above the CSS customization form, there is a link to reset all your changes and get back to the normal BGA. Please '''bookmark this link''' before doing any change to your CSS code. If you break the website by any manner, you'll be able to restore the original BGA instantly. = Modify images = Most of images on BGA are loaded through "background-image" CSS command. This way, you can update it and load any image. You can host image on any server, or on a website like [http://imgur.com/ imgur]. = Sharing customization = Using the link above the CSS customization form, you can share your customization with anyone. Please DO NOT send a link that break the website. If we detect some attempt to fool users, we will immediately take action against you. = Troubleshooting = == The CSS code I wrote is not taken into account == At first, check the sourcecode of the BGA page. If your CSS code does not appear there, then the most probable reason is that you did a syntax error in your CSS code, so we didn't take a part of your code into account. If it appears, then it should be an error in one of your declaration (ex: wrong #id). a4e8517f29981a28bf14cfb1ff2a1c0b39a46e04 1563 1562 2015-06-17T15:54:59Z Sourisdudesert 1 wikitext text/x-wiki This feature allows you to customize Board Game Arena with some CSS. = Why this feature? = At first, because this is cool :) Then, a lot of players told us that BGA should look better, and we constantly tried to make it look much better. But as it is a community-based website, we found out that we should allow YOU to participate. So this is why you can customize BGA appearance and share your customization with others. = How it works? = From your account preferences, "advanced" tab, you can write some CSS. As soon as you click on "save", it is integrated to BGA CSS for your account. You should use your browser developer tools (F12 on Chrome and Firefox) to get the ids/classes of the element that you want to change, and try to change them with these tools first. Finally, you can copy/paste your updates on the CSS customization form. = What is CSS ? = Well... if you don't know what CSS is, sorry but you shouldn't try to customize BGA appearance with this tool. = Reset CSS = Just above the CSS customization form, there is a link to reset all your changes and get back to the normal BGA. Please '''bookmark this link''' before doing any change to your CSS code. If you break the website by any manner, you'll be able to restore the original BGA instantly. = Modify images = Most of images on BGA are loaded through "background-image" CSS command. This way, you can update it and load any image. You can host image on any server, or on a website like [http://imgur.com/ imgur]. = Sharing customization = Using the link above the CSS customization form, you can share your customization with anyone. Please DO NOT send a link that break the website. If we detect some attempt to fool users, we will immediately take action against you. = Troubleshooting = == The CSS code I wrote is not taken into account == At first, check the sourcecode of the BGA page. If your CSS code does not appear there, then the most probable reason is that you did a syntax error in your CSS code, so we didn't take a part of your code into account. If it appears, then it should be an error in one of your declaration (ex: wrong #id). f160c4d2c00b6e6f08ff4d91bbbf3b0c12d147f5 1568 1563 2015-07-07T20:10:38Z Een 3 /* How it works? */ wikitext text/x-wiki This feature allows you to customize Board Game Arena with some CSS. = Why this feature? = At first, because this is cool :) Then, a lot of players told us that BGA should look better, and we constantly tried to make it look much better. But as it is a community-based website, we found out that we should allow YOU to participate. So this is why you can customize BGA appearance and share your customization with others. = How does it work? = From your account preferences, "advanced" tab, you can write some CSS. As soon as you click on "save", it is integrated to BGA CSS for your account. You should use your browser developer tools (F12 on Chrome and Firefox) to get the ids/classes of the element that you want to change, and try to change them with these tools first. Finally, you can copy/paste your updates on the CSS customization form. = What is CSS ? = Well... if you don't know what CSS is, sorry but you shouldn't try to customize BGA appearance with this tool. = Reset CSS = Just above the CSS customization form, there is a link to reset all your changes and get back to the normal BGA. Please '''bookmark this link''' before doing any change to your CSS code. If you break the website by any manner, you'll be able to restore the original BGA instantly. = Modify images = Most of images on BGA are loaded through "background-image" CSS command. This way, you can update it and load any image. You can host image on any server, or on a website like [http://imgur.com/ imgur]. = Sharing customization = Using the link above the CSS customization form, you can share your customization with anyone. Please DO NOT send a link that break the website. If we detect some attempt to fool users, we will immediately take action against you. = Troubleshooting = == The CSS code I wrote is not taken into account == At first, check the sourcecode of the BGA page. If your CSS code does not appear there, then the most probable reason is that you did a syntax error in your CSS code, so we didn't take a part of your code into account. If it appears, then it should be an error in one of your declaration (ex: wrong #id). df7c4dd1f612c924060f4af35c8f768aee0a8539 1569 1568 2015-07-07T20:11:42Z Een 3 /* Modify images */ wikitext text/x-wiki This feature allows you to customize Board Game Arena with some CSS. = Why this feature? = At first, because this is cool :) Then, a lot of players told us that BGA should look better, and we constantly tried to make it look much better. But as it is a community-based website, we found out that we should allow YOU to participate. So this is why you can customize BGA appearance and share your customization with others. = How does it work? = From your account preferences, "advanced" tab, you can write some CSS. As soon as you click on "save", it is integrated to BGA CSS for your account. You should use your browser developer tools (F12 on Chrome and Firefox) to get the ids/classes of the element that you want to change, and try to change them with these tools first. Finally, you can copy/paste your updates on the CSS customization form. = What is CSS ? = Well... if you don't know what CSS is, sorry but you shouldn't try to customize BGA appearance with this tool. = Reset CSS = Just above the CSS customization form, there is a link to reset all your changes and get back to the normal BGA. Please '''bookmark this link''' before doing any change to your CSS code. If you break the website by any manner, you'll be able to restore the original BGA instantly. = Modify images = Most of the images on BGA are loaded through "background-image" CSS command. This way, you can update it and load any image. You can host image on any server, or on a website like [http://imgur.com/ imgur]. = Sharing customization = Using the link above the CSS customization form, you can share your customization with anyone. Please DO NOT send a link that break the website. If we detect some attempt to fool users, we will immediately take action against you. = Troubleshooting = == The CSS code I wrote is not taken into account == At first, check the sourcecode of the BGA page. If your CSS code does not appear there, then the most probable reason is that you did a syntax error in your CSS code, so we didn't take a part of your code into account. If it appears, then it should be an error in one of your declaration (ex: wrong #id). 4403c8a5dd9b2997c41242ef8d2266c6a436dd63 1570 1569 2015-07-07T20:12:59Z Een 3 /* Sharing customization */ wikitext text/x-wiki This feature allows you to customize Board Game Arena with some CSS. = Why this feature? = At first, because this is cool :) Then, a lot of players told us that BGA should look better, and we constantly tried to make it look much better. But as it is a community-based website, we found out that we should allow YOU to participate. So this is why you can customize BGA appearance and share your customization with others. = How does it work? = From your account preferences, "advanced" tab, you can write some CSS. As soon as you click on "save", it is integrated to BGA CSS for your account. You should use your browser developer tools (F12 on Chrome and Firefox) to get the ids/classes of the element that you want to change, and try to change them with these tools first. Finally, you can copy/paste your updates on the CSS customization form. = What is CSS ? = Well... if you don't know what CSS is, sorry but you shouldn't try to customize BGA appearance with this tool. = Reset CSS = Just above the CSS customization form, there is a link to reset all your changes and get back to the normal BGA. Please '''bookmark this link''' before doing any change to your CSS code. If you break the website by any manner, you'll be able to restore the original BGA instantly. = Modify images = Most of the images on BGA are loaded through "background-image" CSS command. This way, you can update it and load any image. You can host image on any server, or on a website like [http://imgur.com/ imgur]. = Sharing customization = Using the link above the CSS customization form, you can share your customization with anyone. Please DO NOT send a link that breaks the website. If we detect some attempt to fool users, we will immediately take action against you. = Troubleshooting = == The CSS code I wrote is not taken into account == At first, check the sourcecode of the BGA page. If your CSS code does not appear there, then the most probable reason is that you did a syntax error in your CSS code, so we didn't take a part of your code into account. If it appears, then it should be an error in one of your declaration (ex: wrong #id). c2dc5a36ea41822dfc525878f9728727f3194daf Gamehelplox 0 196 1564 2015-06-18T16:27:06Z Websteria 9150 English Rules wikitext text/x-wiki Lords Of Xidit Rules (EN): [[https://boardgamegeek.com/filepage/104981/lords-xidit-english-rules]] 72e58ea58e71b4cc8a13056397d4af78993007a6 1566 1564 2015-06-26T12:20:20Z 4wire 9238 wikitext text/x-wiki Lords Of Xidit Rules (EN): [[https://boardgamegeek.com/filepage/104981/lords-xidit-english-rules]] This a hidden move programming game, similar to RoboRally. The goal is to gather all kinds of fighter classes on "recruiting" towns (grey background disk) and defeat monsters threatening the towns with a white background disk. To defeat a monster you need to have all classes of fighters shown at the bottom of the disk. 14209093b5a5a099339e240acdb60e10f55db48d 1567 1566 2015-06-26T12:24:59Z 4wire 9238 wikitext text/x-wiki Lords Of Xidit Rules (EN): [[https://boardgamegeek.com/filepage/104981/lords-xidit-english-rules]] This a hidden move programming game, similar to RoboRally. The goal is to gather all kinds of fighter classes on "recruiting" towns (grey background disk) and defeat monsters threatening the towns with a white background disk. To defeat a monster you need to have all classes of fighters shown at the bottom of the disk. When a round starts, each player programs his move board with either a : - color of path to follow - a white and green symbol to action at the location - a yellow x to wait at the location And submit their choices. f73b6b864d9c8d51ac5809a0f2dad440be686a91 Multipleaccounts 0 164 1565 1361 2015-06-25T10:54:50Z Sourisdudesert 1 wikitext text/x-wiki == The Main Rule == '''One BGA account = One person''' == Playing from the same IP == This is '''authorized''' to play at the same table from the same IP (internet address). The warning message "this player plays from the same internet address as another player" is a '''simple warning'''. It is a useful warning, because the other players have the right to know that there are players at their table that are able to discuss out of game. If you want to play from the same internet address as another person: * The best option is not to play at the same table, or play at a table where you know everyone. * Please '''switch off ELO''' (table option), so you won't be accused of cheating. * If you play with strangers, make them comfortable with the fact you are 2 (or more) different people: don't discuss about the game outside the chatroom, don't collaborate (or do kingmaking) with your partner. When some of your opponents are playing from the same IP: * You may politely refuse to play with them. * You should be vigilant and check that they are not collaborating during the game. * You don't have to report them until they are doing a concrete kingmaking action. If you report some players saying that "they are playing from the same IP" without any kingmaking proof, we will close your report. == Boosting your ELO by playing against yourself == This is the most stupid and useless thing to do on BGA. Why? Because this is very easy to detect, and because the penalty is: * all your secondary account are removed. * your primary account is reset to 1500 ELO for all games. Why this is so easy to detect: * When you start having a very good ELO, all other good players will look at you and your game history. In the game history, this is really easy to see how you manage to have a good ELO. * In BGA, every game can be replayed. So if a game is suspect, anyone can replay it and check if this is a real game or a fake game. * In addition to this, we are using some automatic methods and some technical information that allow us to check if "one person = one account". * Consequently, it happens that some players manage to do ELO boosting, but at the end they are all detected and reset to 1500. This is why this is a waste of time for everyone, and this is why this is useless. If you have a lot of time to spend, please try to get better at this game and please do not try to cheat. '''忙郎中文机器翻译: 主要规则 一个BGA帐户=一个人。 警告消息“这个玩家与另一名玩家在相同的网络地址”是一个简单的警告。 这是一个有用的警告,因为其他玩家有权知道有玩家在他们的桌子,可以一起讨论游戏。 如果你想从相同的网络地址和另一个人玩,最好的选择是不在同一张桌子上玩,或者玩的一张桌子上,每个人你都认识。 如果跟你玩的是陌生人,让他们确认你们是2个不同的人:不讨论游戏,不与您的合作伙伴合作。 当你的对手是来自同一个IP:你可以礼貌地拒绝和他们一起玩。 你要提高警惕,检查他们游戏中不合作。 你不需要报告他们直到他们作弊。如果你报告说“他们是在同一IP”却没有任何证明,我们将关闭你的报告。 在对提高你自己的ELO方面,这是最愚蠢和无用的东西。为什么?因为这很容易识别,而且会有刑罚: 你所有的帐户被删除。您的主帐户所有游戏分值都将被重置到1500以下。 “一个人就是一个帐户”。 如果你有很多时间,请尝试在这方面做得更好的游戏,请不要试图欺骗。 ''' f5460d0ff4d757c9c899e5275d08682a6b911c25 Gamehelpflorenzacardgame 0 197 1571 2015-07-10T18:51:25Z Greenman 1407 Created page with "Game Round is divided into 4 phases: * Draw Artists and Monuments * Draw Florenza Cards * Take Actions **Play Florenza Card **Complete a Monument **Reserve Monument or Artist ..." wikitext text/x-wiki Game Round is divided into 4 phases: * Draw Artists and Monuments * Draw Florenza Cards * Take Actions **Play Florenza Card **Complete a Monument **Reserve Monument or Artist **Activate Location Card **Send Out Workers **Go to Market **Search for Inspiration * End of Round **Discard Cards except one **Collect Income **Elect the Captain of the People **Reset Location Cards Game End: Game ends after 5 rounds. 833eb8149df9353b8b85f07c41f81a7a260570d1 1572 1571 2015-07-10T18:58:03Z Greenman 1407 wikitext text/x-wiki Game Round is divided into 4 phases: * Draw Artists and Monuments * Draw Florenza Cards * Take Actions (4 per round plus extras given from played cards) **Play Florenza Card **Complete a Monument **Reserve Monument or Artist **Activate Location Card (collect/sell resource of face up card) **Send Out Workers (collect 50 Fiorini) **Go to Market (sell/buy/trade to supply) **Search for Inspiration (draw extra card) * End of Round **Discard Cards except one **Collect Income **Elect the Captain of the People **Reset Location Cards Game End: Game ends after 5 rounds. 20c87a84c8420c17df98f9f72cb4c90f1246b51b 1573 1572 2015-07-10T18:58:35Z Greenman 1407 wikitext text/x-wiki Game Round is divided into 4 phases: * Draw Artists and Monuments * Draw Florenza Cards * Take Actions (4 per round plus extras given from played cards) **Play Florenza Card **Complete a Monument **Reserve Monument or Artist **Activate Location Card (collect/sell resource of face up card) **Send Out Workers (collect 50 Fiorini) **Go to Market (sell/buy/trade to supply) **Search for Inspiration (draw extra card) * End of Round **Discard Cards except one **Collect Income **Elect the Captain of the People **Reset Location Cards Game End: Game ends after 5 rounds. 6ba7844694494bff62e42595d0b5418cae02784b 1574 1573 2015-07-10T18:59:27Z Greenman 1407 adding spaces for view in game wikitext text/x-wiki Game Round is divided into 4 phases: * Draw Artists and Monuments * Draw Florenza Cards * Take Actions (4 per round plus extras given from played cards) **Play Florenza Card **Complete a Monument **Reserve Monument or Artist **Activate Location Card (collect/sell resource of face up card) **Send Out Workers (collect 50 Fiorini) **Go to Market (sell/buy/trade to supply) **Search for Inspiration (draw extra card) * End of Round **Discard Cards except one **Collect Income **Elect the Captain of the People **Reset Location Cards Game End: Game ends after 5 rounds. 4720977eafab4fcc82954282a0e0eb95f301b69b 1575 1574 2015-07-10T19:00:02Z Greenman 1407 wikitext text/x-wiki '''Game Round is divided into 4 phases:''' * Draw Artists and Monuments * Draw Florenza Cards * Take Actions (4 per round plus extras given from played cards) **Play Florenza Card **Complete a Monument **Reserve Monument or Artist **Activate Location Card (collect/sell resource of face up card) **Send Out Workers (collect 50 Fiorini) **Go to Market (sell/buy/trade to supply) **Search for Inspiration (draw extra card) * End of Round **Discard Cards except one **Collect Income **Elect the Captain of the People **Reset Location Cards ''' Game End:''' Game ends after 5 rounds. a54e229b04280f0d68112e24b0ddca7f7889d919 1576 1575 2015-07-10T19:00:42Z Greenman 1407 wikitext text/x-wiki '''Game Round is divided into 4 phases:''' * Draw Artists and Monuments * Draw Florenza Cards * Take Actions (4 per round plus extras given from played cards) **Play Florenza Card **Complete a Monument **Reserve Monument or Artist **Activate Location Card (collect/sell resource of face up card) **Send Out Workers (collect 50 Fiorini) **Go to Market (sell/buy/trade to supply) **Search for Inspiration (draw extra card) * End of Round **Discard Cards except one **Collect Income **Elect the Captain of the People **Reset Location Cards . . . ''' Game End:''' Game ends after 5 rounds. 83a8ab2f15b6c52e16827122c7c848825e08ba6e 1577 1576 2015-07-10T19:01:07Z Greenman 1407 wikitext text/x-wiki '''Game Round is divided into 4 phases:''' * Draw Artists and Monuments * Draw Florenza Cards * Take Actions (4 per round plus extras given from played cards) **Play Florenza Card **Complete a Monument **Reserve Monument or Artist **Activate Location Card (collect/sell resource of face up card) **Send Out Workers (collect 50 Fiorini) **Go to Market (sell/buy/trade to supply) **Search for Inspiration (draw extra card) * End of Round **Discard Cards except one **Collect Income **Elect the Captain of the People **Reset Location Cards _ _ ''' Game End:''' Game ends after 5 rounds. 4492da6fa869e197c9f25c0e950740e10ba498b7 1578 1577 2015-07-10T19:05:17Z Greenman 1407 wikitext text/x-wiki '''Game Round is divided into 4 phases:''' * Draw Artists and Monuments * Draw Florenza Cards * Take Actions (4 per round plus extras given from played cards) **Play Florenza Card **Complete a Monument **Reserve Monument or Artist **Activate Location Card (collect/sell resource of face up card) **Send Out Workers (collect 50 Fiorini) **Go to Market (sell/buy/trade to supply) **Search for Inspiration (draw extra card) * End of Round **Discard Cards except one **Collect Income **Elect the Captain of the People **Reset Location Cards '''Game ends''' after 5 rounds. cdd6804dff04796a67dd6edbca245dfbd845eac8 Gamehelpsechsnimmt 0 174 1579 1371 2015-07-20T23:54:00Z Dirtysaboteur 5683 /* Playing the game */ wikitext text/x-wiki == 6 nimmt! == The basic goal of the game is to avoid having to pick up cards, and try to force the other players to do so. Everyone starts with 66 points - you lose one for each "beef head" on a card you have to pick up. When one player has lost all of their points, the game will end at the end of the current round and the player with the most points left wins! === Playing the game === Everyone starts a round with 10 cards in their hand. Four cards are placed on the table to start four rows. Every player secretly chooses a card, and then all of the cards are revealed at the same time. When the cards are revealed, they are placed on the ends of rows, from lowest value played to highest, following two rules: 1. cards are always placed in ascending order. 2. cards are always placed next to the card on the board with the smallest difference between them. As play progresses, the rows will fill up with cards - at five cards, a row is full. If someone's card would go onto a full row, that player has to pick up all of the cards in that row, and they lose as many points as there are "beef heads" on the cards (different cards are worth different amounts - more on that in a moment). The card that the person played becomes the starting point of a new row. If someone plays a card that is lower than the numbers at the end of all of the rows, then that player must take a row of their choice, and start a new row in its place with their card. '''Bull heads''' Each card has a number of bull heads on it - this indicates how many points it is worth when it is picked up. Cards which end in the number "5" (ex. 5, 15, 25) are worth 2 points. Cards which end in the number "0" (10, 20, 30) are worth 3 points. Cards which have double numbers (11, 22, 33) are worth 5 points. The "55" card has both a "5" and double numbers, and is worth 7 points. All other cards are worth 1 point. '''End of a round''' Once a round ends, if no one has lost all of their points, then a new round begins. If someone is out of points, then the game is over and whoever still has the most points is the winner. === Alternate Rules === '''Tactics:''' This ruleset changes the number of cards in play based on how many people are playing - other than that the rules are the same. The number of cards is equal to the number of players plus 4, so every card that could be played will find its way onto the table at some point. This changes strategy some and makes paying attention to which cards are have yet to be played important. '''Logic:''' The same as Tactics, except that at the start of the round all of the cards are placed on the table face up, and players take turns choosing cards one at a time to build their hands before the round proper starts. fe7da336069b2f9a65c271a564e50db47ba25dc8 Tutorial gomoku 0 73 1580 1545 2015-07-21T11:43:08Z Coin-coin le canapin 2264 /* You will start from our 'emtpy game' template */ wikitext text/x-wiki This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [http://en.wikipedia.org/wiki/Gomoku '''Gomoku'''] (also known as Gobang or Five in a Row). == You will start from our 'empty game' template == Here is how your games looks by default when it has just been created: [[File:Gomoku tuto1.png]] == Setup the board == Gather useful images for the game and edit them as needed. Upload them in the 'img' folder of your SFTP access. Edit .tpl to add some divs for the board in the HTML. For example: <pre> <div id="gmk_game_area"> <div id="gmk_background"> <div id="gmk_goban"> </div> </div> </div> </pre> Edit .css to set the div sizes and positions and show the image of the board as background. <pre> #gmk_game_area { text-align: center; position: relative; } #gmk_background { width: 620px; height: 620px; position: relative; display: inline-block; } #gmk_goban { background-image: url( 'img/goban.jpg'); width: 620px; height: 620px; position: absolute; } </pre> [[File:Gomoku tuto2.png]] == Setup the backbone of your game == Edit dbmodel.sql to create a table for intersections. We need coordinates for each intersection and a field to store the color of the stone on this intersection (if any). <pre> CREATE TABLE IF NOT EXISTS `intersection` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `coord_x` tinyint(2) unsigned NOT NULL, `coord_y` tinyint(2) unsigned NOT NULL, `stone_color` varchar(8) NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Edit .game.php->setupNewGame() to insert the empty intersections (19x19) with coordinates into the database. <pre> // Insert (empty) intersections into database $sql = "INSERT INTO intersection (coord_x, coord_y) VALUES "; $values = array(); for ($x = 0; $x < 19; $x++) { for ($y = 0; $y < 19; $y++) { $values[] = "($x, $y)"; } } $sql .= implode( $values, ',' ); self::DbQuery( $sql ); </pre> Edit .game.php->getAllDatas() to retrieve the state of the intersections from the database. <pre> // Intersections $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection "; $result['intersections'] = self::getCollectionFromDb( $sql ); </pre> Edit .tpl to create a template for intersections. <pre> var jstpl_intersection='<div class="gmk_intersection ${stone_type}" id="intersection_${x}_${y}"></div>'; </pre> Define the styles for the intersection divs. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; } </pre> Edit .js->setup() to setup the intersections layer that will be used to get click events and to display the stones. The data you returned in $result['intersections'] in .game.php->getAllDatas() is now available in your .js->setup() in gamedatas.intersections. <pre> // Setup intersections for( var id in gamedatas.intersections ) { var intersection = gamedatas.intersections[id]; dojo.place( this.format_block('jstpl_intersection', { x:intersection.coord_x, y:intersection.coord_y, stone_type:(intersection.stone_color == null ? "no_stone" : 'stone_' + intersection.stone_color) } ), $ ( 'gmk_background' ) ); var x_pix = this.getXPixelCoordinates(intersection.coord_x); var y_pix = this.getYPixelCoordinates(intersection.coord_y); this.slideToObjectPos( $('intersection_'+intersection.coord_x+'_'+intersection.coord_y), $('gmk_background'), x_pix, y_pix, 10 ).play(); if (intersection.stone_color != null) { // This intersection is taken, it shouldn't appear as clickable anymore dojo.removeClass( 'intersection_' + intersection.coord_x + '_' + intersection.coord_y, 'clickable' ); } } </pre> Use some temporary css border-color or background-color and opacity to see the divs and make sure you have them positioned right. <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-color: blue; opacity: 0.3; } </pre> You can declare some constants in material.inc.php and pass them to your .js for easy repositioning (modify constant, refresh). This is especially useful if the same constants have to be used on the server and on the client. * Declare your constants in material.inc.php (this will be automatically included in your .game.php) <pre> $this->gameConstants = array( "INTERSECTION_WIDTH" => 30, "INTERSECTION_HEIGHT" => 30, "INTERSECTION_X_SPACER" => 2.8, // Float "INTERSECTION_Y_SPACER" => 2.8, // Float "X_ORIGIN" => 0, "Y_ORIGIN" => 0, ); </pre> * In .game.php->getAllDatas(), add the constants to the result array // Constants $result['constants'] = $this->gameConstants; * In .js constructor, define a class variable for constants // Game constants this.gameConstants = null; * In .js->setup() assign the constants to this variable this.gameConstants = gamedatas.constants; * Then use it in your getXPixelCoordinates and getYPixelCoordinates functions getXPixelCoordinates: function( intersection_x ) { return this.gameConstants['X_ORIGIN'] + intersection_x * (this.gameConstants['INTERSECTION_WIDTH'] + this.gameConstants['INTERSECTION_X_SPACER']); }, getYPixelCoordinates: function( intersection_y ) { return this.gameConstants['Y_ORIGIN'] + intersection_y * (this.gameConstants['INTERSECTION_HEIGHT'] + this.gameConstants['INTERSECTION_Y_SPACER']); }, Here is what you should get: [[File:Gomoku tuto3.png]] == Manage states and events == Define your game states in states.inc.php. For gomoku we will use 3 states in addition of the predefined states 1 (gameSetup) and 99 (gameEnd). One to play, one to check the end game condition, one to give his turn to the other player if the game is not over. The first state requires an action from the player, so its type is 'activeplayer'. The two others are automatic actions for the game, so their type is 'game'. We will update the progression while checking for the end of the game, so for this state we set the 'updateGameProgression' flag to true. <pre> 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a stone'), "descriptionmyturn" => clienttranslate('${you} must play a stone'), "type" => "activeplayer", "possibleactions" => array( "playStone" ), "transitions" => array( "stonePlayed" => 3, "zombiePass" => 3 ) ), 3 => array( "name" => "checkEndOfGame", "description" => '', "type" => "game", "action" => "stCheckEndOfGame", "updateGameProgression" => true, "transitions" => array( "gameEnded" => 99, "notEndedYet" => 4 ) ), 4 => array( "name" => "nextPlayer", "description" => '', "type" => "game", "action" => "stNextPlayer", "transitions" => array( "" => 2 ) ), </pre> Implement the 'stNextPlayer()' function in .game.php to manage turn rotation. Except if there are special rules for the game turn depending on context, this is really easy: <pre> function stNextPlayer() { self::trace( "stNextPlayer" ); // Go to next player $active_player = self::activeNextPlayer(); self::giveExtraTime( $active_player ); $this->gamestate->nextState(); } </pre> Add onclick events on intersections in .js->setup() // Add events on active elements (the third parameter is the method that will be called when the event defined by the second parameter happens - this method must be declared beforehand) this.addEventToClass( "gmk_intersection", "onclick", "onClickIntersection"); Declare the corresponding .js->onClickIntersection() function, which calls an action function on the server with appropriate parameters <pre> onClickIntersection: function( evt ) { console.log( '$$$$ Event : onClickIntersection' ); dojo.stopEvent( evt ); if( ! this.checkAction( 'playStone' ) ) { return; } var node = evt.currentTarget.id; var coord_x = node.split('_')[1]; var coord_y = node.split('_')[2]; console.log( '$$$$ Selected intersection : (' + coord_x + ', ' + coord_y + ')' ); if ( this.isCurrentPlayerActive() ) { this.ajaxcall( "/gomoku/gomoku/playStone.html", { lock: true, coord_x: coord_x, coord_y: coord_y }, this, function( result ) {}, function( is_error ) {} ); } }, </pre> Add this action function in .action.php, retrieving parameters and calling the appropriate game action <pre> public function playStone() { self::setAjaxMode(); // Retrieve arguments // Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method $coord_x = self::getArg( "coord_x", AT_posint, true ); $coord_y = self::getArg( "coord_y", AT_posint, true ); // Then, call the appropriate method in your game logic, like "playCard" or "myAction" $this->game->playStone( $coord_x, $coord_y ); self::ajaxResponse( ); } </pre> Add game action in .game.php to update the database, send a notification to the client providing the event notified (‘stonePlayed’) and its parameters, and proceed to the next state. <pre> function playStone( $coord_x, $coord_y ) { // Check that this is player's turn and that it is a "possible action" at this game state (see states.inc.php) self::checkAction( 'playStone' ); $player_id = self::getActivePlayerId(); // Check that this intersection is free $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE coord_x = $coord_x AND coord_y = $coord_y AND stone_color is null "; $intersection = self::getObjectFromDb( $sql ); if ($intersection == null) { throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); } // Get player color $sql = "SELECT player_id, player_color FROM player WHERE player_id = $player_id "; $player = self::getNonEmptyObjectFromDb( $sql ); $color = ($player['player_color'] == 'ffffff' ? 'white' : 'black'); // Update the intersection with a stone of the appropriate color $intersection_id = $intersection['id']; $sql = "UPDATE intersection SET stone_color = '$color' WHERE id = $intersection_id "; self::DbQuery($sql); // Notify all players self::notifyAllPlayers( "stonePlayed", clienttranslate( '${player_name} dropped a stone on ${coord_x},${coord_y}' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'coord_x' => $coord_x, 'coord_y' => $coord_y, 'color' => $color ) ); // Go to next game state $this->gamestate->nextState( "stonePlayed" ); } </pre> Catch the notification in .js->setupNotifications() and link it to a javascript function to execute when the notification is received. <pre> setupNotifications: function() { console.log( 'notifications subscriptions setup' ); dojo.subscribe( 'stonePlayed', this, "notif_stonePlayed" ); } </pre> Implement this function in javascript to update the intersection to show the stone, and register it inside the setNotifications function. <pre> notif_stonePlayed: function( notif ) { console.log( '**** Notification : stonePlayed' ); console.log( notif ); // Create a stone dojo.place( this.format_block('jstpl_stone', { stone_type:'stone_' + notif.args.color, x:notif.args.coord_x, y:notif.args.coord_y } ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ) ); // Place it on the player panel this.placeOnObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'player_board_' + notif.args.player_id ) ); // Animate a slide from the player panel to the intersection dojo.style( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y, 'zIndex', 1 ); var slide = this.slideToObject( $( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ), $( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y ), 1000 ); dojo.connect( slide, 'onEnd', this, dojo.hitch( this, function() { // At the end of the slide, update the intersection dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'no_stone' ); dojo.addClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'stone_' + notif.args.color ); dojo.removeClass( 'intersection_' + notif.args.coord_x + '_' + notif.args.coord_y, 'clickable' ); // We can now destroy the stone since it is now visible through the change in style of the intersection dojo.destroy( 'stone_' + notif.args.coord_x + '_' + notif.args.coord_y ); })); slide.play(); }, </pre> For this function to work properly, you also need: * to declare a stone javascript template in your .tpl file. <pre> var jstpl_stone='<div class="gmk_stone ${stone_type}" id="stone_${x}_${y}"></div>'; </pre> * to define the css styles for the stones <pre> .gmk_intersection { width: 30px; height: 30px; position: relative; background-image: url( 'img/stones.png' ); } .gmk_stone { width: 30px; height: 30px; position: absolute; background-image: url( 'img/stones.png' ); } .no_stone { background-position: -60px 0px; } .stone_black { background-position: 0px 0px; } .stone_white { background-position: -30px 0px; } </pre> These styles rely on an PNG image (with transparent background) of both the white and black stones, and positions the background appropriately to show only the part of the background image matching the appropriate stone (or the transparent space if there is no stone). Here is what the image looks like: [[File:Gomoku stones.png]] The red circle is used to highlight intersections where you can drop a stone when the player's cursor hovers over them (we also change the cursor to a hand). To do this: * we define in the css file the 'clickable' css class <pre> .clickable { cursor: pointer; } .clickable:hover { background-position: -90px 0px; } </pre> * in .js, when we enter the 'playerTurn' state, we add the 'clickable' style to the intersections where there is no stone <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': if( this.isCurrentPlayerActive() ) { var queueEntries = dojo.query( '.no_stone' ); for(var i=0; i<queueEntries.length; i++) { dojo.addClass( queueEntries[i], 'clickable' ); } } } }, </pre> Finally, make sure to modify the default colors for players to white and black $default_colors = array( "000000", "ffffff", ); The basic game turn is implemented: you can now drop some stones! [[File:Gomoku tuto4.png]] == Cleanup your styles == Remove temporary css visualisation helpers : looks good! [[File:Gomoku tuto5.png]] == Implement rules and end of game conditions == Implement specific rules for the game. For example in Gomoku, black plays first. So in .game.php->setupNewGame(), at the end of the setup make the black player active: <pre> // Black plays first $sql = "SELECT player_id, player_name FROM player WHERE player_color = '000000' "; $black_player = self::getNonEmptyObjectFromDb( $sql ); $this->gamestate->changeActivePlayer( $black_player['player_id'] ); </pre> Implement rule for computing game progression in .game.php->getGameProgression(). For Gomoku we will use the rate of occupied intersections over the total number of intersections. This will often be wildly inaccurate as the game can end pretty quickly, but it's about the best we can do (the game can drag to a stalemate with all intersections occupied and no winner). <pre> function getGameProgression() { // Compute and return the game progression // Number of stones laid down on the goban over the total number of intersections * 100 $sql = " SELECT round(100 * count(id) / (19*19) ) as value from intersection WHERE stone_color is not null "; $counter = self::getNonEmptyObjectFromDB( $sql ); return $counter['value']; } </pre> Implement end of game detection and update the score according to who is the winner. It is easier to check for a win directly after setting the stone, so: * declare a global 'end_of_game' variable in .game.php->Gomoku() self::initGameStateLabels( array( "end_of_game" => 10, ) ); * init that global variable to 0 in .game.php->setupNewGame() self::setGameStateInitialValue( 'end_of_game', 0 ); * add the appropriate code in .game.php before proceeding to the next state, using a checkForWin() function implemented separately for clarity. If the game has been won, we set the score, send a score update notification to the client side, and set the 'end_of_game' global variable to 1 as a flag signaling that the game has ended. <pre> // Check if end of game has been met if ($this->checkForWin( $coord_x, $coord_y, $color )) { // Set active player score to 1 (he is the winner) $sql = "UPDATE player SET player_score = 1 WHERE player_id = $player_id"; self::DbQuery($sql); // Notify final score $this->notifyAllPlayers( "finalScore", clienttranslate( '${player_name} wins the game!' ), array( "player_name" => self::getActivePlayerName(), "player_id" => $player_id, "score_delta" => 1, ) ); // Set global variable flag to pass on the information that the game has ended self::setGameStateValue('end_of_game', 1); // End of game message $this->notifyAllPlayers( "message", clienttranslate('Thanks for playing!'), array( ) ); } </pre> * Then in the gomoku->stCheckEndOfGame() function which is called when your state machine goes to the 'checkEndOfGame' state, check for this variable and for other possible 'end of game' conditions (draw). <pre> function stCheckEndOfGame() { self::trace( "stCheckEndOfGame" ); $transition = "notEndedYet"; // If there is no more free intersections, the game ends $sql = "SELECT id, coord_x, coord_y, stone_color FROM intersection WHERE stone_color is null"; $free = self::getCollectionFromDb( $sql ); if (count($free) == 0) { $transition = "gameEnded"; } // If the 'end of game' flag has been set, end the game if (self::getGameStateValue('end_of_game') == 1) { $transition = "gameEnded"; } $this->gamestate->nextState( $transition ); } </pre> * Catch the score notification on the client side in .js->setupNotifications(). It is advised to set up a small delay after that so that end of game popup doesn't show too quickly. <pre> dojo.subscribe( 'finalScore', this, "notif_finalScore" ); this.notifqueue.setSynchronous( 'finalScore', 1500 ); </pre> * Implement the function declared to handle the notification. <pre> notif_finalScore: function( notif ) { console.log( '**** Notification : finalScore' ); console.log( notif ); // Update score this.scoreCtrl[ notif.args.player_id ].incValue( notif.args.score_delta ); }, </pre> '''Test everything thoroughly... you are done!''' [[File:Gomoku tuto6.png]] 869b2cf61b15027477c4b6bd7f351825213cf2c5 Game database model: dbmodel.sql 0 92 1581 719 2015-07-26T09:19:51Z Een 3 wikitext text/x-wiki In this file you specify the database schema of your game. This file contains SQL queries that will be executed during the creation of your game table. '''Note:''' you can't change the database schema during the game. == Create your schema == To build this file, we recommend you to build the tables you need with the PhpMyAdmin tool (see BGA user guide), and then to export them and to copy/paste the content inside this file. '''Note:''' you must not use for a column the same name as for the table, as the framework replay function relies on regexp substitution to save/restore a previous state in a clone table with another name. == Default tables == Important: by default, BGA creates 4 tables for your game: global, stats, gamelog, and player. You must not modify the schema of global, stats and gamelog tables (and you must not access them directly with SQL queries in your PHP code). You may add columns to "player" table. This is very practical to add simple values associated with players. Example: <pre> ALTER TABLE `player` ADD `player_reserve_size` SMALLINT UNSIGNED NOT NULL DEFAULT '7'; </pre> For your information, the useful columns of default "player" table are: * player_no: the index of player in natural playing order. * player_id * player_name: (note: you should better access this date with getActivePlayerName() or loadPlayersBasicInfos() methods) * player_score: the current score of the player (displayed in the player panel). You must update this field to update player's scores. * player_score_aux: the secondary score, used as a tie breaker. You must update this field according to tie breaking rules of the game (see also: [[Main_game_logic:_yourgamename.game.php#Manage_player_scores_and_Tie_breaker|Manage_player_scores_and_Tie_breaker]]) == CREATE TABLES == you can create tables, using engine InnoDB <pre> CREATE TABLE IF NOT EXISTS `hands` ( `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `player_id` TINYINT(1) NOT NULL, `1` BOOL NOT NULL DEFAULT 1, `2` BOOL NOT NULL DEFAULT 1, `3` BOOL NOT NULL DEFAULT 1, `4` BOOL NOT NULL DEFAULT 1, `5` BOOL NOT NULL DEFAULT 1, `6` BOOL NOT NULL DEFAULT 1, `7` BOOL NOT NULL DEFAULT 1, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> '''Note''': if you put comments, you cannot do it in same line than code, <pre> `3` BOOL NOT NULL DEFAULT 1, -- activated or not </pre> will comment also starting from `3` BOOL, and code will not be taken into account. == Link == You can add your Db inits in function SetupNewGame() from file 'gamename.game.php' == Errors Log == To trace Database creation check the logs that you can access in /admin/studio. a93288c4c3827632474c9a590a0be3663a89cc5b Game meta-information: gameinfos.inc.php 0 130 1582 976 2015-07-27T19:45:43Z Rudolf 2790 Adding Category. wikitext text/x-wiki From this file, you can edit the various meta-information of your game. Once you modified the file, don't forget to click on "Reload game informations" from the Control Panel in order in can be taken into account. Most information provided in this file are self-explainable. Some information, though: * You are not allowed to set the "'''is_beta'''" to 0 before the game has been released on BGA and stabilized. * "'''fast/medium/slow_additional_time'''": please set high values here: after the game has been released, we will lower these value to match the real game duration. * "'''players'''": during the first step of development of a game, you'd better allow the "1 player" configuration: much easy to start/stop a game this way. * '''suggest_player_number''' / '''not_recommend_player_number''': don't specify anything here if there is no configuration that is REALLY better/worst than another one. You can check player's poll on BoardGameGeek game page if you have any doubt. == Tags == Any number of '''Tags''' can be attribute to your game. Tags are useful to place your game in the correct place and to give a good quick overview of what the game is about to players. Main game category (you MUST specify one tag AND ONLY ONE from this category): * 1: Abstract game * 2: Casual games * 3: For regular players * 4: For core gamers Other tags (you can specify any numbers of tags): * 10: Short game (<10 minutes) * 11: Medium length game (10 minutes to 30 minutes) * 12: Long game (>30mn) * 20: Awarded game (Win a prestigious award) (the game must have been at the '''first''' place of one the [http://boardgamegeek.com/wiki/page/Gaming_Industry_Awards# following major awards list]). * 22: Prototype (This game has not been published yet) * 23: Classic (This game is a classic from Public Domain) * 30: 2 players (2p game / best with 2 players) * 100: Fantasy theme * 101: Science Fiction them * 102: Historical theme * 103: Adventure * 104: Exploration * 105: Conquest * 106: Building * 107: Espionage theme * 200: Card game (Cards plays a central role in this game) * 201: Dice * 202: Solo game * 203: Worker placement * 204: Hand management * 205: Bluff * 206: Tile placement * 207: Combinations * 208: Majority * 209: Race * 210: Collection dce3069317afd2c832e825d78368920a208217aa 1583 1582 2015-07-29T01:47:13Z Pikiou 1872 warning on the minimum number of players bug wikitext text/x-wiki From this file, you can edit the various meta-information of your game. Once you modified the file, don't forget to click on "Reload game informations" from the Control Panel in order in can be taken into account. Most information provided in this file are self-explainable. Some information, though: * You are not allowed to set the "'''is_beta'''" to 0 before the game has been released on BGA and stabilized. * "'''fast/medium/slow_additional_time'''": please set high values here: after the game has been released, we will lower these value to match the real game duration. * "'''players'''": ** during the first step of development of a game, you'd better allow the "1 player" configuration: much easy to start/stop a game this way. ** if you change the minimum number of players from for example 1 to 2, make sure the new tables you create are not restricted from 1 to 1 player otherwise when you create a new table and this account setting is used, there will be a conflict with the new minimum number of players allowed. * '''suggest_player_number''' / '''not_recommend_player_number''': don't specify anything here if there is no configuration that is REALLY better/worst than another one. You can check player's poll on BoardGameGeek game page if you have any doubt. == Tags == Any number of '''Tags''' can be attribute to your game. Tags are useful to place your game in the correct place and to give a good quick overview of what the game is about to players. Main game category (you MUST specify one tag AND ONLY ONE from this category): * 1: Abstract game * 2: Casual games * 3: For regular players * 4: For core gamers Other tags (you can specify any numbers of tags): * 10: Short game (<10 minutes) * 11: Medium length game (10 minutes to 30 minutes) * 12: Long game (>30mn) * 20: Awarded game (Win a prestigious award) (the game must have been at the '''first''' place of one the [http://boardgamegeek.com/wiki/page/Gaming_Industry_Awards# following major awards list]). * 22: Prototype (This game has not been published yet) * 23: Classic (This game is a classic from Public Domain) * 30: 2 players (2p game / best with 2 players) * 100: Fantasy theme * 101: Science Fiction them * 102: Historical theme * 103: Adventure * 104: Exploration * 105: Conquest * 106: Building * 107: Espionage theme * 200: Card game (Cards plays a central role in this game) * 201: Dice * 202: Solo game * 203: Worker placement * 204: Hand management * 205: Bluff * 206: Tile placement * 207: Combinations * 208: Majority * 209: Race * 210: Collection 96e3684ed940715c43a96145866f8be29485de6e Gamehelpchinagold 0 136 1584 1403 2015-07-30T01:56:02Z Senatorhung 4176 wikitext text/x-wiki A Tactical Dice Game by Günter Cornett for 2 players of 8 years and up (Original Translation: Ben Baldanza) '''What China Gold is about''': Both players are searching for gold, one in the mountains and the other in the rivers. If all the gold of a prospecting area of a mountain or a river is found, the mountain or river player can claim the gold. But note that every prospecting area is at the same moment part of a mountain and part of a river. Thus the players are racing to see who can collect the gold first from each area. '''The Game Board''': 12 mountains, 12 rivers and 61 Prospecting Areas are shown on the game board. The Prospecting Areas are represented both as mountains (brown planes) and as rivers (blue lines). '''Game Play''': On each turn, the sum of the random discs indicates how many Prospecting Area Markers may be turned face up. The Prospecting Area Markers to be turned MUST lie side by side in a straight line, without a gap or previously discovered lumps of gold in between. Instead of turning the thrown number of Prospecting Area Markers face up, the player may hide exactly one nugget again by turning one Prospecting Area Marker face down. When the last marker in one of the player's areas (mountain or river) is turned face up, all of the gold in this area can be claimed. If the last Prospecting Area Marker in one of the opponent's areas is turned face up at the same time, the opponent then claims the gold in this area. '''Small Disc Reduction''': Five not yet turned Prospecting Area Markers in a straight line make two different possibilities to turn four Prospecting Area Markers face up. When there is at most one straight line of five Prospecting Area Markers neighboring in straight line that could be turned face up, the small disc 0/1 is returned to the box. For the remainder of the game, small discs 0/2 and 1/2 will be used so that only numbers from 1 to 4 will be available. Four not yet turned Prospecting Area Markers in a straight line make two different possibilities to turn three Prospecting Area Markers face up. When there is at most one straight line of four Prospecting Area Markers neighboring in straight line that could be turned face up, the small disc 0/2 is replaced with the small disc 0/1 from the box so that only numbers from 1 to 3 will be available. If turning back a Prospecting Area Marker creates a situation with more possibilities to turn free Prospecting Area Markers in straight line face up, the appropriate number of small discs is used. When there is at most one straight line of three Prospecting Area Markers neighboring in straight line that could be turned face up, all small discs are returned to the box. From now on the players may choose between turning a single or two neighbouring Prospecting Area Markers face up. '''Game End''': When all Prospecting Areas are cleared, the player who collected the most gold is the winner ! c1b37625e97034cf17e827abac2b100e4751ea4f Gamehelpspyrium 0 198 1585 2015-07-31T06:28:51Z Rainn 5818 Created page with "Maximum number of workers: 7" wikitext text/x-wiki Maximum number of workers: 7 134678b8cee0637057672a681cae75944575b85d Gamehelptargi 0 169 1586 1546 2015-07-31T14:10:20Z Squarerootofthree 5668 Undo revision 1546 by [[Special:Contributions/Saubohne5000|Saubohne5000]] ([[User talk:Saubohne5000|talk]]) wikitext text/x-wiki Each round of play has the following stages: # Players take turns playing their three "targi" (meeples) on the border cards. Targi may not be placed in the same row or column as your opponent's Targi. # Place 1 or 2 "tribal markers" in the middle of the game board at the intersection of the rows/columns of your targi. # You may then activate the cards under each of your pieces. These cards may give you more goods, or they may let you spend your goods to purchase special cards to place in your personal tableau. You may only hold 3 gold and 10 goods total between rounds. The game ends when a player has filled their tableau, or when the robber has completed one jog around the map. In addition to the victory points earned during the game and from special card abilities, you also get: * 4 victory points for a building a row of identical cards in your tableau, and * 2 victory points for a row of all different cards ef10617beccf314c5918ba24f45e64085dbbb879 Game clock 0 15 1587 1497 2015-08-01T16:06:56Z Drmashirito 9136 /* Game clock system philosophy */ wikitext text/x-wiki [[Category:Help]] On '''Board Game Arena''' you are playing "live" (real time) or "turn-based" (asynchronously). In both cases, you have an allotted delay to play your moves. Most of the time, your initial delay at the beginning of a game is some minutes (in realtime mode) or some days (in turn-based mode). During each turn, or on specific occasions, you get an additional delay. If you have no more time to play, you will get a "clock" penalty and your opponents can decide to skip your turns (and consequently make you loose the game). == Game clock system philosophy == The game clock has been designed with the following principles: * Even if you are in a losing position, this is always more interesting (for your ELO and your reputation) to play the game until the end. * Make sure that if your opponent left the game (or has been disconnected), it won't take long before you can expel him and win the game by forfeit. * Expelling an opponent is always a volunteer action, so you can agree with your opponent to forget the time limit if you want to. * If your opponent does not play and run out of time, this is always more interesting for you to try to make him back into the game than to punish him with penalties or skipping turn. In anyway, don't forget that respecting your allotted time is VERY important. == Time to think == Your allotted time to think is displayed on the right of your player's name. When it's your turn to play, this time is also displayed at the top of the web page. == Game speed == Table administrator can make a choice between some game speed profile (example: fast, normal, slow). There are many speeds for each mode (realtime and turn-based). The additional amount of time credited each turn depends on the chosen game speed profile. Be careful to check the game speed setting before the game starts to adjust your timing. The interface displays an estimation of the game duration based on recently played games with the same speed settings. Note: your allotted time to think cannot get higher that your initial time to think. For example, if you start the game with 5 minutes of thinking time, you time will be limited to 5 minutes maximum. Note: playing without a time limit is strongly discouraged, except if you are playing with friends, or to discover a new game. Remember that without time limit, you can't skip the turn of a player that is not playing. == Running out of time == As soon as you run out of time (negative clock), you get a clock penalty. When a player has a negative clock, any one of his opponents can make him skip his turn. Once this has been done, all following turns are skipped automatically. After player A's turn has been "skipped" at y% of game progression, the game results are "neutralized". It means that: * Player A is going to loose the game anyway (last position), with the corresponding ELO loss. * In addition, Player A will get a "leave" penalty on his profile and an additional -10 ELO points penalty. * Player A's opponents are going to win the game anyway (all tied at the first position), with y% of the ELO points they would have normally won. This is impossible to lose points when your opponent left the game. Example: player "Albert" left a 2 players game at 50% of the game progression. His opponent "Ben" skips his turn. At the end of the game, "Albert" will get -30 ELO points (normal loss for a game loss) plus an additional -10 ELO points (penalty for leaving), plus a red "leave" penalty on his reputation profile. "Ben" is going to win 15 ELO points (50% of the normal 30 ELO points win). Note: you can't skip the turn of an opponent if your own clock is even more negative than him. For example, if "Ben"'s clock is -3:45 and "Albert"'s clock is "-0:05", Albert can expel Ben but Ben cannot expel Albert. == Continue the game after a "skip turn" == If you are playing in a game where a player skips all his turns, you may continue the game if you like, or not. This has no effect on anything (game results, penalties, and so on...). This is "just for fun". == "My opponent is too slow" == Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his allotted time to think. If you want to play fast, set up or join only tables with "fast" mode on, but don't bully an opponent to play when he has the right to use his alloted time to think. == "I would like to think a little" == If you are in a critical step of the game and want to take some time to think, you can click on the "I would like to think a little" link at the top right of the page. Thus, your opponents will get a message and won't be thinking that you are away from keyboard or disconnected. Clicking on this link is not mandatory, but we encourage its use as a courtesy. ad1854167822b41e3d74af2061e86bd7e20cafc1 Gamehelpnoirkvi 0 199 1588 2015-08-03T23:07:55Z Ch huang 8005 Classic Mode Rule wikitext text/x-wiki = GAME STRUCTURE = The two players alternate turns, each taking one action. The first turn for each player is a little different than the rest, but afterwards, all turns are the same. The Killer always goes first. = Classic Mode = == FIRST TURN – KILLER == On the first turn, the Killer must make a Kill action. To do this, he chooses one of the suspect cards on the board adjacent (either on the sides or the diagonals) to his secret identity, and turns that card face-down, to its deceased side. == FIRST TURN – INSPECTOR == The Inspector must now select one of the 4 cards from his hand to be his secret identity. He sets that card face-down in front of him. He loses if this person is killed. The others he keeps in hand as ‘evidence cards’. == LATER TURNS – KILLER == On each turn, the Killer must choose one of the following 3 actions and perform it. '''Shift''' a row or column '''Kill''' an adjacent suspect '''Disguise''' himself (or attempt to) == LATER TURNS – INSPECTOR == On each turn, the Inspector must choose one of the following 3 actions and perform it. '''Shift''' a row or column '''Arrest''' an adjacent suspect or yourself '''Exonerate''' a suspect from the deck == SHIFT ACTION == Example of shifting a column down. The suspect who ‘falls off’ goes into the new empty slot. Both players have the ability to shift. To do so, select any row or column on the board You do not have to be in it or near the chosen row or column. Move all cards in the column vertically up or down, or move all cards in the row left or right. This will cause one card to ‘fall off’ the edge of the board. Place the card that falls off onto the new empty space on the other side. NOTE: You cannot use your shift to ‘undo’ the previous player’s shift. For example, if a player shifts a row right, the next move cannot be to shift that same row left. == KILL ACTION == The Killer can kill a suspect just like he did on the first turn. He just picks a suspect who is adjacent to his character on the board, and turns that suspect to its deceased side. Since the Inspector is now one of the suspects, if the Inspector is killed, he reveals his identity and the killer wins! Otherwise, play continues. == ARREST ACTION == The Inspector can arrest a suspect whom he is adjacent to on the board. He may even arrest himself to throw off suspicion. He simply points at the suspect and asks the killer “Are you [name]?” If the killer is the named suspect, the Inspector wins! Otherwise, play continues. == DISGUISE ACTION == The Killer can disguise himself to throw the Inspector off his trail. To do this, he draws a card from the top of the Evidence Deck, and then secretly checks to see if that character is still live on the board. If it is still alive, he discards his current identity and turns that card to its deceased side, then places the card he drew face-down in front of him. It is his new secret identity. If the suspect is deceased, he simply discards the card face up, and retains his old identity. His turn is over either way. == EXONERATE ACTION == The Inspector draws one card from the Evidence Deck into his evidence hand. He must then discard a card from his hand face-up beside the board (if the discarded suspect is still live, it is easier to place the innocent card over top of their suspect card on the board). After Exonerating, the Inspector’s turn is over, and he should have 3 cards in his evidence hand. == OTHER RULES == If the Evidence Deck is exhausted, the Disguise and Exonerate actions are no longer available. If an entire row or column of suspects are deceased, that row or column is removed, and the board shrinks. If 16 characters are deceased at any time, the game ends and the Killer wins. 348ae40962fb8115156d1b622f7585811dac053f 1589 1588 2015-08-03T23:12:39Z Ch huang 8005 wikitext text/x-wiki = Game Structure = The two players alternate turns, each taking one action. The first turn for each player is a little different than the rest, but afterwards, all turns are the same. The Killer always goes first. = Classic Mode = == FIRST TURN – KILLER == On the first turn, the Killer must make a Kill action. To do this, he chooses one of the suspect cards on the board adjacent (either on the sides or the diagonals) to his secret identity, and turns that card face-down, to its deceased side. == FIRST TURN – INSPECTOR == The Inspector must now select one of the 4 cards from his hand to be his secret identity. He sets that card face-down in front of him. He loses if this person is killed. The others he keeps in hand as ‘evidence cards’. == LATER TURNS – KILLER == On each turn, the Killer must choose one of the following 3 actions and perform it. '''Shift''' a row or column '''Kill''' an adjacent suspect '''Disguise''' himself (or attempt to) == LATER TURNS – INSPECTOR == On each turn, the Inspector must choose one of the following 3 actions and perform it. '''Shift''' a row or column '''Arrest''' an adjacent suspect or yourself '''Exonerate''' a suspect from the deck == SHIFT ACTION == Example of shifting a column down. The suspect who ‘falls off’ goes into the new empty slot. Both players have the ability to shift. To do so, select any row or column on the board You do not have to be in it or near the chosen row or column. Move all cards in the column vertically up or down, or move all cards in the row left or right. This will cause one card to ‘fall off’ the edge of the board. Place the card that falls off onto the new empty space on the other side. NOTE: You cannot use your shift to ‘undo’ the previous player’s shift. For example, if a player shifts a row right, the next move cannot be to shift that same row left. == KILL ACTION == The Killer can kill a suspect just like he did on the first turn. He just picks a suspect who is adjacent to his character on the board, and turns that suspect to its deceased side. Since the Inspector is now one of the suspects, if the Inspector is killed, he reveals his identity and the killer wins! Otherwise, play continues. == ARREST ACTION == The Inspector can arrest a suspect whom he is adjacent to on the board. He may even arrest himself to throw off suspicion. He simply points at the suspect and asks the killer “Are you [name]?” If the killer is the named suspect, the Inspector wins! Otherwise, play continues. == DISGUISE ACTION == The Killer can disguise himself to throw the Inspector off his trail. To do this, he draws a card from the top of the Evidence Deck, and then secretly checks to see if that character is still live on the board. If it is still alive, he discards his current identity and turns that card to its deceased side, then places the card he drew face-down in front of him. It is his new secret identity. If the suspect is deceased, he simply discards the card face up, and retains his old identity. His turn is over either way. == EXONERATE ACTION == The Inspector draws one card from the Evidence Deck into his evidence hand. He must then discard a card from his hand face-up beside the board (if the discarded suspect is still live, it is easier to place the innocent card over top of their suspect card on the board). After Exonerating, the Inspector’s turn is over, and he should have 3 cards in his evidence hand. == OTHER RULES == If the Evidence Deck is exhausted, the Disguise and Exonerate actions are no longer available. If an entire row or column of suspects are deceased, that row or column is removed, and the board shrinks. If 16 characters are deceased at any time, the game ends and the Killer wins. = Standard Mode = In Standard Mode, when you disguise or exonorate, you put the innocent card you discard down onto the board, face-up, covering the existing suspect. If the suspect is already deceased, then don't do this. If you Exonorate (whether you place the suspect or not), you canvas the area around that suspect for the killer. If you kill a suspect marked as innocent, you get to canvas the area around that suspect for the inspector. e3f28c726ae4aebda1b63d6975503f49ba62dfe5 1590 1589 2015-08-03T23:15:42Z Ch huang 8005 wikitext text/x-wiki == Game Structure == The two players alternate turns, each taking one action. The first turn for each player is a little different than the rest, but afterwards, all turns are the same. The Killer always goes first. == Classic Mode == == First Turn – Killer == On the first turn, the Killer must make a Kill action. To do this, he chooses one of the suspect cards on the board adjacent (either on the sides or the diagonals) to his secret identity, and turns that card face-down, to its deceased side. == First Turn – Inspector == The Inspector must now select one of the 4 cards from his hand to be his secret identity. He sets that card face-down in front of him. He loses if this person is killed. The others he keeps in hand as ‘evidence cards’. == Later Turns – Killer == On each turn, the Killer must choose one of the following 3 actions and perform it. '''Shift''' a row or column '''Kill''' an adjacent suspect '''Disguise''' himself (or attempt to) == Later Turns – Inspector == On each turn, the Inspector must choose one of the following 3 actions and perform it. '''Shift''' a row or column '''Arrest''' an adjacent suspect or yourself '''Exonerate''' a suspect from the deck == Shift Action == Example of shifting a column down. The suspect who ‘falls off’ goes into the new empty slot. Both players have the ability to shift. To do so, select any row or column on the board You do not have to be in it or near the chosen row or column. Move all cards in the column vertically up or down, or move all cards in the row left or right. This will cause one card to ‘fall off’ the edge of the board. Place the card that falls off onto the new empty space on the other side. NOTE: You cannot use your shift to ‘undo’ the previous player’s shift. For example, if a player shifts a row right, the next move cannot be to shift that same row left. == Kill Action == The Killer can kill a suspect just like he did on the first turn. He just picks a suspect who is adjacent to his character on the board, and turns that suspect to its deceased side. Since the Inspector is now one of the suspects, if the Inspector is killed, he reveals his identity and the killer wins! Otherwise, play continues. == Arrest Action == The Inspector can arrest a suspect whom he is adjacent to on the board. He may even arrest himself to throw off suspicion. He simply points at the suspect and asks the killer “Are you [name]?” If the killer is the named suspect, the Inspector wins! Otherwise, play continues. == Disguise Action == The Killer can disguise himself to throw the Inspector off his trail. To do this, he draws a card from the top of the Evidence Deck, and then secretly checks to see if that character is still live on the board. If it is still alive, he discards his current identity and turns that card to its deceased side, then places the card he drew face-down in front of him. It is his new secret identity. If the suspect is deceased, he simply discards the card face up, and retains his old identity. His turn is over either way. == Exonerate Action == The Inspector draws one card from the Evidence Deck into his evidence hand. He must then discard a card from his hand face-up beside the board (if the discarded suspect is still live, it is easier to place the innocent card over top of their suspect card on the board). After Exonerating, the Inspector’s turn is over, and he should have 3 cards in his evidence hand. == Other Rules == If the Evidence Deck is exhausted, the Disguise and Exonerate actions are no longer available. If an entire row or column of suspects are deceased, that row or column is removed, and the board shrinks. If 16 characters are deceased at any time, the game ends and the Killer wins. == Standard Mode == In Standard Mode, when you disguise or exonorate, you put the innocent card you discard down onto the board, face-up, covering the existing suspect. If the suspect is already deceased, then don't do this. If you Exonorate (whether you place the suspect or not), you canvas the area around that suspect for the killer. If you kill a suspect marked as innocent, you get to canvas the area around that suspect for the inspector. 051ff807445f5f596b519b55834358a72959a808 1591 1590 2015-08-03T23:17:18Z Ch huang 8005 wikitext text/x-wiki == Game Structure == The two players alternate turns, each taking one action. The first turn for each player is a little different than the rest, but afterwards, all turns are the same. The Killer always goes first. == Classic Mode == == First Turn – Killer == On the first turn, the Killer must make a Kill action. To do this, he chooses one of the suspect cards on the board adjacent (either on the sides or the diagonals) to his secret identity, and turns that card face-down, to its deceased side. == First Turn – Inspector == The Inspector must now select one of the 4 cards from his hand to be his secret identity. He sets that card face-down in front of him. He loses if this person is killed. The others he keeps in hand as ‘evidence cards’. == Later Turns – Killer == On each turn, the Killer must choose one of the following 3 actions and perform it. '''Shift''' a row or column '''Kill''' an adjacent suspect '''Disguise''' himself (or attempt to) == Later Turns – Inspector == On each turn, the Inspector must choose one of the following 3 actions and perform it. '''Shift''' a row or column '''Arrest''' an adjacent suspect or yourself '''Exonerate''' a suspect from the deck == Shift Action == Both players have the ability to shift. To do so, select any row or column on the board You do not have to be in it or near the chosen row or column. Move all cards in the column vertically up or down, or move all cards in the row left or right. This will cause one card to ‘fall off’ the edge of the board. Place the card that falls off onto the new empty space on the other side. NOTE: You cannot use your shift to ‘undo’ the previous player’s shift. For example, if a player shifts a row right, the next move cannot be to shift that same row left. == Kill Action == The Killer can kill a suspect just like he did on the first turn. He just picks a suspect who is adjacent to his character on the board, and turns that suspect to its deceased side. Since the Inspector is now one of the suspects, if the Inspector is killed, he reveals his identity and the killer wins! Otherwise, play continues. == Arrest Action == The Inspector can arrest a suspect whom he is adjacent to on the board. He may even arrest himself to throw off suspicion. He simply points at the suspect and asks the killer “Are you [name]?” If the killer is the named suspect, the Inspector wins! Otherwise, play continues. == Disguise Action == The Killer can disguise himself to throw the Inspector off his trail. To do this, he draws a card from the top of the Evidence Deck, and then secretly checks to see if that character is still live on the board. If it is still alive, he discards his current identity and turns that card to its deceased side, then places the card he drew face-down in front of him. It is his new secret identity. If the suspect is deceased, he simply discards the card face up, and retains his old identity. His turn is over either way. == Exonerate Action == The Inspector draws one card from the Evidence Deck into his evidence hand. He must then discard a card from his hand face-up beside the board (if the discarded suspect is still live, it is easier to place the innocent card over top of their suspect card on the board). After Exonerating, the Inspector’s turn is over, and he should have 3 cards in his evidence hand. == Other Rules == If the Evidence Deck is exhausted, the Disguise and Exonerate actions are no longer available. If an entire row or column of suspects are deceased, that row or column is removed, and the board shrinks. If 16 characters are deceased at any time, the game ends and the Killer wins. == Standard Mode == In Standard Mode, when you disguise or exonorate, you put the innocent card you discard down onto the board, face-up, covering the existing suspect. If the suspect is already deceased, then don't do this. If you Exonorate (whether you place the suspect or not), you canvas the area around that suspect for the killer. If you kill a suspect marked as innocent, you get to canvas the area around that suspect for the inspector. 820b8226ef119821a3f309456a5c66d591abac8b 1592 1591 2015-08-03T23:18:00Z Ch huang 8005 wikitext text/x-wiki == Game Structure == The two players alternate turns, each taking one action. The first turn for each player is a little different than the rest, but afterwards, all turns are the same. The Killer always goes first. == Classic Mode == == First Turn – Killer == On the first turn, the Killer must make a Kill action. To do this, he chooses one of the suspect cards on the board adjacent (either on the sides or the diagonals) to his secret identity, and turns that card face-down, to its deceased side. == First Turn – Inspector == The Inspector must now select one of the 4 cards from his hand to be his secret identity. He sets that card face-down in front of him. He loses if this person is killed. The others he keeps in hand as ‘evidence cards’. == Later Turns – Killer == On each turn, the Killer must choose one of the following 3 actions and perform it. '''Shift''' a row or column '''Kill''' an adjacent suspect '''Disguise''' himself (or attempt to) == Later Turns – Inspector == On each turn, the Inspector must choose one of the following 3 actions and perform it. '''Shift''' a row or column '''Arrest''' an adjacent suspect or yourself '''Exonerate''' a suspect from the deck == Shift Action == Both players have the ability to shift. To do so, select any row or column on the board You do not have to be in it or near the chosen row or column. Move all cards in the column vertically up or down, or move all cards in the row left or right. This will cause one card to ‘fall off’ the edge of the board. Place the card that falls off onto the new empty space on the other side. NOTE: You cannot use your shift to ‘undo’ the previous player’s shift. For example, if a player shifts a row right, the next move cannot be to shift that same row left. == Kill Action == The Killer can kill a suspect just like he did on the first turn. He just picks a suspect who is adjacent to his character on the board, and turns that suspect to its deceased side. Since the Inspector is now one of the suspects, if the Inspector is killed, he reveals his identity and the killer wins! Otherwise, play continues. == Arrest Action == The Inspector can arrest a suspect whom he is adjacent to on the board. He may even arrest himself to throw off suspicion. He simply points at the suspect and asks the killer “Are you [name]?” If the killer is the named suspect, the Inspector wins! Otherwise, play continues. == Disguise Action == The Killer can disguise himself to throw the Inspector off his trail. To do this, he draws a card from the top of the Evidence Deck, and then secretly checks to see if that character is still live on the board. If it is still alive, he discards his current identity and turns that card to its deceased side, then places the card he drew face-down in front of him. It is his new secret identity. If the suspect is deceased, he simply discards the card face up, and retains his old identity. His turn is over either way. == Exonerate Action == The Inspector draws one card from the Evidence Deck into his evidence hand. He must then discard a card from his hand face-up beside the board (if the discarded suspect is still live, it is easier to place the innocent card over top of their suspect card on the board). After Exonerating, the Inspector’s turn is over, and he should have 3 cards in his evidence hand. == Other Rules == If the Evidence Deck is exhausted, the Disguise and Exonerate actions are no longer available. If an entire row or column of suspects are deceased, that row or column is removed, and the board shrinks. If 16 characters are deceased at any time, the game ends and the Killer wins. == Standard Mode == In Standard Mode, when you disguise or exonorate, you put the innocent card you discard down onto the board, face-up, covering the existing suspect. If the suspect is already deceased, then don't do this. If you Exonorate (whether you place the suspect or not), you canvas the area around that suspect for the killer. If you kill a suspect marked as innocent, you get to canvas the area around that suspect for the inspector. e1db3f0fa1a748aa94a93c596f22407c4dde1ba1 Gamehelpthroughtheages 0 168 1593 1200 2015-08-05T04:59:43Z Jackchance 9725 Added info about how wonders increase in civil action cost. wikitext text/x-wiki During your turn, you may spend your '''actions points''' to: * pick cards from the card rows (if you have room in your hand) ** Wonders cost an addition civil action for each wonder you have finished * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * build/upgrade military units '''Yellow counters''' represent your population. They can be in one of three places: * on the cards on your tableau * on your available worker pool * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in two places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce food or resources Building up your civilisation: * '''Food''' lets you move workers from your yellow bank to your available worker pool. * '''Resources''' let you move workers from your available worker pool to a card on your tableau. * '''Science''' (light bulbs) lets you move cards from your hand to your tableau. * When your population grows, you will need to produce more '''happiness''' or your workers will stop working. * Producing '''culture''' will earn you victory points. * Producing more '''military strength''' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars In the Advanced and Complete games, '''additional points are scored at the end of the game''' according to special event cards. But at the end of the Simple game, additional points are scored the same way every game: * 2 culture scored per 1 Strength (military) * 2 culture scored per Happy Face * 2 culture scored per level 1 technology in play * 1 culture scored per food or resource production per turn * 1 culture scored per 1 Science Rating (science gained per turn) a812497d96d5bd917c6be8382cd941aff23da181 1598 1593 2015-08-21T04:06:43Z Jackchance 9725 wikitext text/x-wiki During your turn, you may spend your '''actions points''' to: * pick cards from the card rows (if you have room in your hand) ** Wonders cost an addition civil action for each wonder you have finished * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * build/upgrade military units '''Yellow counters''' represent your population. They can be in one of three places: * on the cards on your tableau * on your available worker pool * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in three places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce food or resources * on your wonder, marking how far along it's construction is Building up your civilisation: * '''Food''' lets you move workers from your yellow bank to your available worker pool. * '''Resources''' let you move workers from your available worker pool to a card on your tableau. * '''Science''' (light bulbs) lets you move cards from your hand to your tableau. * When your population grows, you will need to produce more '''happiness''' or your workers will stop working. * Producing '''culture''' will earn you victory points. * Producing more '''military strength''' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars In the Advanced and Complete games, '''additional points are scored at the end of the game''' according to special event cards. But at the end of the Simple game, additional points are scored the same way every game: * 2 culture scored per 1 Strength (military) * 2 culture scored per Happy Face * 2 culture scored per level 1 technology in play * 1 culture scored per food or resource production per turn * 1 culture scored per 1 Science Rating (science gained per turn) d73b84e0cfef77ad079c8d04c790e1b794b5d6e9 Gamehelphive 0 167 1594 1225 2015-08-05T17:21:53Z Snake eyes 9730 changed "be" to "Bee" wikitext text/x-wiki Each turn, you may either place an insect or move an insect. All insects in play must be contiguous at all times. The first player's Queen Bee to be surrounded on all sides loses. You must place your Queen Bee by your fourth turn. Movement rules: * Queen Bee: Can only move one space * Beetle: Only one space, but it can move on top of another insect * Spider: 3 spaces in one direction * Grasshopper: Moves to the next open space in a straight line * Soldier Ant: It can move an unlimited amount along outside borders Expansion Pieces: * Mosquito: Uses the movement ability of any piece it is touching * Ladybug: Travels two spaces on top of other pieces and one space back down * Pill bug: Can move a single space, or move a piece currently adjacent to it to another adjacent location This is just a brief summary of movement rules. This has a comprehensive overview of movement rules: http://boardgamegeek.com/thread/371756/hive-detailed-review ccc0bc612426f59ec0c26789c62aa58358dab997 1600 1594 2015-08-26T16:07:01Z Saizai 9917 + tournament opening rule /via https://boardgamegeek.com/wiki/page/Hive_FAQ wikitext text/x-wiki Each turn, you may either place an insect or move an insect. All insects in play must be contiguous at all times. The first player's Queen Bee to be surrounded on all sides loses. You must place your Queen Bee by your fourth turn. Tournament opening rule: You cannot place your queen as your first move. Movement rules: * Queen Bee: Can only move one space * Beetle: Only one space, but it can move on top of another insect * Spider: 3 spaces in one direction * Grasshopper: Moves to the next open space in a straight line * Soldier Ant: It can move an unlimited amount along outside borders Expansion Pieces: * Mosquito: Uses the movement ability of any piece it is touching * Ladybug: Travels two spaces on top of other pieces and one space back down * Pill bug: Can move a single space, or move a piece currently adjacent to it to another adjacent location This is just a brief summary of movement rules. This has a comprehensive overview of movement rules: http://boardgamegeek.com/thread/371756/hive-detailed-review 45857a46109cccb1744c7fb62cb7e1eedf9819ce Game statistics: stats.inc.php 0 95 1595 519 2015-08-08T23:08:34Z Pikiou 1872 Copy/paste of the explanations inside stats.inc.php wikitext text/x-wiki (to be completed) In this file, you are describing game statistics, that will be displayed at the end of the game. !! After modifying this file, you must use "Reload statistics configuration" in BGA Studio backoffice ("Your game configuration" section): http://en.studio.boardgamearena.com/admin/studio There are 2 types of statistics: _ table statistics, that are not associated to a specific player (ie: 1 value for each game). _ player statistics, that are associated to each players (ie: 1 value for each player in the game). Statistics types can be "int" for integer, "float" for floating point values, and "bool" for boolean Once you defined your statistics there, you can start using "initStat", "setStat" and "incStat" method in your game logic, using statistics names defined below. !! It is not a good idea to modify this file when a game is running !! If your game is already public on BGA, please read the following before any change: http://en.doc.boardgamearena.com/Post-release_phase#Changes_that_breaks_the_games_in_progress Notes: * Statistic index is the reference used in setStat/incStat/initStat PHP method * Statistic index must contains alphanumerical characters and no space. Example: 'turn_played' * Statistics IDs must be >=10 * Two table statistics can't share the same ID, two player statistics can't share the same ID * A table statistic can have the same ID than a player statistics * Statistics ID is the reference used by BGA website. If you change the ID, you lost all historical statistic data. Do NOT re-use an ID of a deleted statistic * Statistic name is the English description of the statistic as shown to players 4c2978525d8f2d1d03b2e231808bc9bb65013551 Grade 0 30 1596 1159 2015-08-11T14:06:28Z Monsterhunter5p 9785 /* All grades */ wikitext text/x-wiki Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. == All grades == * '''Mortal''': this is your grade when you just registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraphim can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherubim check that Seraphim are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. * '''Demon''': due to a major terms of use violation, this player is not allowed to do most of the things on the website during a period of time (or forever ......) 9ad4e4cc2f57bf0f53ba7ae4c3e9e3277f941a0c Your game state machine: states.inc.php 0 90 1597 1198 2015-08-20T14:52:30Z Coin-coin le canapin 2264 /* id */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. Note³: When a game is in prod and you change the ID of a state, all active games (including many turn based) will behave unpredictably. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "args" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> === args === (optional) From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state. Example 1 : for Reversi, the list of possible moves during playerTurn state. Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor. Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them. In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them. Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array. Let's see a complete example using args with « Reversi » game : In states.inc.php, we specify some « args » argument for gamestate « playerTurn » : <pre> 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", <================================== HERE "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), </pre> It corresponds to a « argPlayerTurn » method in our PHP code (reversi.game.php): <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves() ); } </pre> Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn : <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> Note: you can also use values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above). Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn). Warning: the "args" method can be called before the "action" method so don't expect data modifications by the "action" method to be available in the "args" method! ==== Private infos in args ==== By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic. This is although possible to specify that some data should be sent to some specific players only: Example 1: send an information to active player(s) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private 'active' => array( // Using "active" keyword inside "_private", you select active player(s) 'somePrivateData' => self::getSomePrivateData() // will be send only to active player(s) ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> Inside the js file, these variables will be available through `args._private`. (e.g. `args._private.somePrivateData` -- it is not `args._private.active.somePrivateData` nor is it `args.somePrivateData`) Example 2: send an information to a specific player (<specific_player_id>) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private <specific_player_id> => array( // you select one specific player with its id 'somePrivateData' => self::getSomePrivateData() // will be send only to <specific_player_id> ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> IMPORTANT: in certain situation (ex: multipleactiveplayer game state) these "private data" features can have a big performance impact. Please do not use if not needed. === updateGameProgression === (optional) IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated. At least one of your game state (any of them) must specify updateGameProgression=>true. d250af18b36824cdfd3aa2319aa2760452d62765 Gamehelpraceforthegalaxy 0 41 1599 1039 2015-08-23T13:37:31Z Twinge 4783 wikitext text/x-wiki In Race for the Galaxy players are competing civilizations exploring space, discovering planets to conquer or settle, building an economy by consuming a planet's goods and building developments. The object of the game is to earn the most victory points from planets and developments played in their tableau, by consuming goods, and from bonuses from special developments. There are five phases to choose from: explore, develop, settle, consume and produce. Players pick one phase per turn (two phases in a two-player game). Then everyone plays only the chosen phases in phase order. Players that chose each phase get an extra benefit. At the end of each round players with more than 10 cards discard down to 10 and a new round begins. The game continues until any player has played 12 cards on their tableau or when the VP pool is exhausted. At the end of that round points are added up. The player with the most points is the winner! In case of a tie, the player with the most goods on the board plus cards in hand wins. You may drag a good (single-coloured small card) to a consumption power to consume it. '''Summary of Phases''' Explore = draw 2 cards; keep 1, discard the other Develop = place and pay for a development Settle = place and pay for a world, receiving any windfall good as indicated Consume = use consume powers if possible, typically to discard goods for victory point chips Produce = place a good on each world without a good that produces one '''Phase Bonuses''' These are the bonuses you gain for choosing each phase: Explore = draw 5 additional cards OR draw 1 additional card and keep 1 additional card Develop = discard 1 less card when paying for the development Settle = draw 1 card after settling a world Consume = Gain double victory points for consumed goods OR trade by discarding a good from play to draw cards equal to its trade value (bonuses from $ row apply) Produce = Produce a good on one windfall world that does not already have a good '''Summary of Goods''' Yellow = Alien Tech (trade value = 5) Green = Genes (4) Brown = Rare Elements (3) Blue = Novelty Goods (2) 46a00b2563d2bacdda5939004aed7116ecb43168 Gamehelpmachiavelli 0 133 1601 1301 2015-08-29T08:51:07Z Chaotic iak 3338 wikitext text/x-wiki Machiavelli is a card game that involves creating Rummy-style sets and runs. Players aim to play all the cards from their hand; the first player to do so wins. == Overview == Machiavelli uses two or more French decks, without including jokers. Each player starts with 15 cards in their hand. They play cards to the table to form combinations, trying to empty their hands the fastest. Players play in turn. In each turn, a player may play any number of cards (including zero), possibly rearranging cards on the table. A player can also draw a card. The turn then passes to the next player. The game runs until someone runs out of cards or the deck is depleted. == Combinations == Cards on the table must always form combinations. There are two types of combinations: sets and runs. In either case, a combination must always consist of at least three cards, and may never include two identical cards. A set is a collection of cards with equal rank (number). A run is a collection of cards with equal suit and consecutive ranks. The ranks are ordered as usual: A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A. Aces are only high or low, they cannot be both. === Examples === * 5♣ 5♦ 5♥ forms a set: there are at least three cards, none of which are identical, and all have the same rank. * 5♣ 5♦ 5♥ 5♠ also forms a set for the same reasons. * 5♣ 5♦ doesn't form a set: there are less than three cards. * 5♣ 5♦ 5♦ doesn't form a set: there are identical cards. * 5♣ 6♣ 7♣ forms a run: there are at least three cards, none of which are identical, all have the same suit, and the ranks are consecutive. * 5♣ 6♣ 7♣ 8♣ also forms a run for the same reasons. * 5♣ 6♣ doesn't form a run: there are less than three cards. * 5♣ 6♣ 8♣ doesn't form a run: the ranks are not consecutive. * A♣ 2♣ 3♣ forms a run; aces can be low. * Q♣ K♣ A♣ forms a run; aces can be high. * K♣ A♣ 2♣ doesn't form a run: aces can't be both low and high. == Playing cards == During a player's turn, the player can play cards to the table, making sure that the table always consists of combinations. The player may introduce a new combination on the table, or they can add cards to an existing combination. As long as the player can play cards, they may do so; they may also stop at any time. For example, the table has the set 5♣ 5♦ 5♥. A player may play a combination, such as 6♣ 6♦ 6♥ or 6♣ 7♣ 8♣, or may extend the existing set by playing 5♠. They may even do both, if they have the appropriate cards. A player may add any number of cards to a single combination: extending A♣ 2♣ 3♣ to A♣ 2♣ 3♣ 4♣ 5♣ 6♣ 7♣ 8♣ 9♣ 10♣ J♣ Q♣ K♣ is allowed. == Rearranging cards == One feature of Machiavelli is that players are allowed to rearrange cards on the table so that their cards can be included. The only condition is that at the end of the turn, all cards on the table must form combinations again; there can be no unmatched cards. In Board Game Arena, rearranging cards is done by picking the cards that are to be rearranged into the hand, and then playing them all back into combinations along with additional cards from the hand. Cards that are picked up from the table will be marked in red, and a player may not end their turn until all these cards are played. A player may decide to click "Restore", which will forfeit their turn, identical to as if they don't play any card in the turn. === Examples === The table consists of a set 5♣ 5♦ 5♥ 5♠ and a run 6♣ 7♣ 8♣. The player wishes to play 4♣. The player removes the 5♣ off the set, adds it to the run, and adds the 4♣ to the run. The table now has a set 5♦ 5♥ 5♠ and a run 4♣ 5♣ 6♣ 7♣ 8♣. The table consists of three sets 5♣ 5♦ 5♥, 6♣ 6♦ 6♥, 7♣ 7♦ 7♥. The player wishes to play 8♣. The player rearranges the sets into runs 5♣ 6♣ 7♣, 5♦ 6♦ 7♦, 5♥ 6♥ 7♥, and adds the 8♣ to the first run. The table now has three runs 5♣ 6♣ 7♣ 8♣, 5♦ 6♦ 7♦, 5♥ 6♥ 7♥ The table consists of two sets 6♣ 6♦ 6♥, 7♣ 7♦ 7♥. The player wishes to play 8♣ by taking the 6♣ and 7♣ off the sets to form a run 6♣ 7♣ 8♣. But this leaves unmatched cards 6♦ 6♥ 7♦ 7♥, so this move is illegal. == Ending a turn == A player may end a turn when the table doesn't have any unmatched cards. If a player ends the turn without playing any card, they must draw one card from the deck; otherwise, they don't draw any additional cards. == End of the game == If a player has no cards in their hand, they immediately win. Otherwise, if the deck is depleted, the player with less cards in their hand wins. Ties are possible; in this case, the tied players are joint winners. cbf91dd0f67c397c6d604f3037f9b53fe3086654 Gamehelpmachiavelli 0 133 1602 1601 2015-08-29T09:16:16Z Chaotic iak 3338 Aces are low wikitext text/x-wiki Machiavelli is a card game that involves creating Rummy-style sets and runs. Players aim to play all the cards from their hand; the first player to do so wins. == Overview == Machiavelli uses two or more French decks, without including jokers. Each player starts with 15 cards in their hand. They play cards to the table to form combinations, trying to empty their hands the fastest. Players play in turn. In each turn, a player may play any number of cards (including zero), possibly rearranging cards on the table. A player can also draw a card. The turn then passes to the next player. The game runs until someone runs out of cards or the deck is depleted. == Combinations == Cards on the table must always form combinations. There are two types of combinations: sets and runs. In either case, a combination must always consist of at least three cards, and may never include two identical cards. A set is a collection of cards with equal rank (number). A run is a collection of cards with equal suit and consecutive ranks. The ranks are ordered as usual, except that aces are always low: A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K. === Examples === * 5♣ 5♦ 5♥ forms a set: there are at least three cards, none of which are identical, and all have the same rank. * 5♣ 5♦ 5♥ 5♠ also forms a set for the same reasons. * 5♣ 5♦ doesn't form a set: there are less than three cards. * 5♣ 5♦ 5♦ doesn't form a set: there are identical cards. * 5♣ 6♣ 7♣ forms a run: there are at least three cards, none of which are identical, all have the same suit, and the ranks are consecutive. * 5♣ 6♣ 7♣ 8♣ also forms a run for the same reasons. * 5♣ 6♣ doesn't form a run: there are less than three cards. * 5♣ 6♣ 8♣ doesn't form a run: the ranks are not consecutive. * A♣ 2♣ 3♣ forms a run; are low. * Q♣ K♣ A♣ doesn't form a run; aces are not high. == Playing cards == During a player's turn, the player can play cards to the table, making sure that the table always consists of combinations. The player may introduce a new combination on the table, or they can add cards to an existing combination. As long as the player can play cards, they may do so; they may also stop at any time. For example, the table has the set 5♣ 5♦ 5♥. A player may play a combination, such as 6♣ 6♦ 6♥ or 6♣ 7♣ 8♣, or may extend the existing set by playing 5♠. They may even do both, if they have the appropriate cards. A player may add any number of cards to a single combination: extending A♣ 2♣ 3♣ to A♣ 2♣ 3♣ 4♣ 5♣ 6♣ 7♣ 8♣ 9♣ 10♣ J♣ Q♣ K♣ is allowed. == Rearranging cards == One feature of Machiavelli is that players are allowed to rearrange cards on the table so that their cards can be included. The only condition is that at the end of the turn, all cards on the table must form combinations again; there can be no unmatched cards. In Board Game Arena, rearranging cards is done by picking the cards that are to be rearranged into the hand, and then playing them all back into combinations along with additional cards from the hand. Cards that are picked up from the table will be marked in red, and a player may not end their turn until all these cards are played. A player may decide to click "Restore", which will forfeit their turn, identical to as if they don't play any card in the turn. === Examples === The table consists of a set 5♣ 5♦ 5♥ 5♠ and a run 6♣ 7♣ 8♣. The player wishes to play 4♣. The player removes the 5♣ off the set, adds it to the run, and adds the 4♣ to the run. The table now has a set 5♦ 5♥ 5♠ and a run 4♣ 5♣ 6♣ 7♣ 8♣. The table consists of three sets 5♣ 5♦ 5♥, 6♣ 6♦ 6♥, 7♣ 7♦ 7♥. The player wishes to play 8♣. The player rearranges the sets into runs 5♣ 6♣ 7♣, 5♦ 6♦ 7♦, 5♥ 6♥ 7♥, and adds the 8♣ to the first run. The table now has three runs 5♣ 6♣ 7♣ 8♣, 5♦ 6♦ 7♦, 5♥ 6♥ 7♥ The table consists of two sets 6♣ 6♦ 6♥, 7♣ 7♦ 7♥. The player wishes to play 8♣ by taking the 6♣ and 7♣ off the sets to form a run 6♣ 7♣ 8♣. But this leaves unmatched cards 6♦ 6♥ 7♦ 7♥, so this move is illegal. == Ending a turn == A player may end a turn when the table doesn't have any unmatched cards. If a player ends the turn without playing any card, they must draw one card from the deck; otherwise, they don't draw any additional cards. == End of the game == If a player has no cards in their hand, they immediately win. Otherwise, if the deck is depleted, the player with less cards in their hand wins. Ties are possible; in this case, the tied players are joint winners. 6ae77124326560c0c81cd4200dc05da43cea4341 Gamehelpquoridor 0 102 1603 889 2015-08-31T12:12:31Z Chaotic iak 3338 wikitext text/x-wiki Quoridor is an abstract board game for 2 or 4 players. Players move their pawns to reach the opposite side before their opponents; however, the defining quality is that players can place walls on the board that block all pawns, thus forcing pawns to navigate their way around the walls. == Start of the game == The board is 9x9 by size. Each player has one pawn, placed in the middle of their respective side. There are 20 walls, distributed equally to all players (10 each for two or 5 each for four). == Player's turn == In a player's turn, a player must do one of the following: * move their pawn, or * place a wall. === Moving a pawn === A player can move a pawn to an adjacent square in the four orthogonal directions (front, back, or sideways). The pawn may not cross past a wall. The pawn may never occupy the same square as an opponent's pawn; if an opponent pawn is adjacent, the player can jump over the opponent's pawn. If there is no wall, no board edge, and no other pawn behind the opponent's pawn, the jump must be straight (the player's pawn moves two squares in that direction). Otherwise, the jump must be diagonal (the player moves to the opponent, then moves sideways). Jumping is never mandatory. === Placing a wall === There are some walls in a player's inventory. Each wall are two squares long. A player may place a wall inside the board, between the squares. The wall may not jut out of the board, and it must be aligned with the grid, so that it blocks two pairs of adjacent squares. A wall blocks all pawns' movements; no pawn can jump over a wall. However, there must always be at least one path for each pawn to reach the opposite side; a wall may not be placed to completely isolate a pawn from their destination side. Note that walls are limited; if a player uses up all their walls, they can no longer place walls. == End of the game == If a player's pawn reaches any one of the nine squares on its destination side, opposite of the starting side, the player wins. f06a45df2c5eeb91919a5a8e2ee57f05979bc379 1609 1603 2015-09-13T12:14:37Z Chaotic iak 3338 wikitext text/x-wiki Quoridor is an abstract board game for 2 or 4 players. Players move their pawns to reach the opposite side before their opponents; however, the defining quality is that players can place walls on the board that block all pawns, thus forcing pawns to navigate their way around the walls. = Rules = == Start of the game == The board is 9x9 by size. Each player has one pawn, placed in the middle of their respective side. There are 20 walls, distributed equally to all players (10 each for two or 5 each for four). == Player's turn == In a player's turn, a player must do one of the following: * move their pawn, or * place a wall. === Moving a pawn === A player can move a pawn to an adjacent square in the four orthogonal directions (front, back, or sideways). The pawn may not cross past a wall. The pawn may never occupy the same square as an opponent's pawn; if an opponent pawn is adjacent, the player can jump over the opponent's pawn. If there is no wall, no board edge, and no other pawn behind the opponent's pawn, the jump must be straight (the player's pawn moves two squares in that direction). Otherwise, the jump must be diagonal (the player moves to the opponent, then moves sideways). Jumping is never mandatory. === Placing a wall === There are some walls in a player's inventory. Each wall are two squares long. A player may place a wall inside the board, between the squares. The wall may not jut out of the board, and it must be aligned with the grid, so that it blocks two pairs of adjacent squares. A wall blocks all pawns' movements; no pawn can jump over a wall. However, there must always be at least one path for each pawn to reach the opposite side; a wall may not be placed to completely isolate a pawn from their destination side. Note that walls are limited; if a player uses up all their walls, they can no longer place walls. == End of the game == If a player's pawn reaches any one of the nine squares on its destination side, opposite of the starting side, the player wins. d5f9c8d16879657235c0c3142c9189603bdd633b 1610 1609 2015-09-13T12:17:20Z Chaotic iak 3338 wikitext text/x-wiki Quoridor is an abstract board game for 2 or 4 players. Players move their pawns to reach the opposite side before their opponents; however, the defining quality is that players can place walls on the board that block all pawns, thus forcing pawns to navigate their way around the walls. == Rules == === Start of the game === The board is 9x9 by size. Each player has one pawn, placed in the middle of their respective side. There are 20 walls, distributed equally to all players (10 each for two or 5 each for four). === Player's turn === In a player's turn, a player must do one of the following: * move their pawn, or * place a wall. ==== Moving a pawn ==== A player can move a pawn to an adjacent square in the four orthogonal directions (front, back, or sideways). The pawn may not cross past a wall. The pawn may never occupy the same square as an opponent's pawn; if an opponent pawn is adjacent, the player can jump over the opponent's pawn. If there is no wall, no board edge, and no other pawn behind the opponent's pawn, the jump must be straight (the player's pawn moves two squares in that direction). Otherwise, the jump must be diagonal (the player moves to the opponent, then moves sideways). Jumping is never mandatory. ==== Placing a wall ==== There are some walls in a player's inventory. Each wall are two squares long. A player may place a wall inside the board, between the squares. The wall may not jut out of the board, and it must be aligned with the grid, so that it blocks two pairs of adjacent squares. A wall blocks all pawns' movements; no pawn can jump over a wall. However, there must always be at least one path for each pawn to reach the opposite side; a wall may not be placed to completely isolate a pawn from their destination side. Note that walls are limited; if a player uses up all their walls, they can no longer place walls. === End of the game === If a player's pawn reaches any one of the nine squares on its destination side, opposite of the starting side, the player wins. 546bb12b3c79ebac1f6632881d62bdec1de0f054 1611 1610 2015-09-13T12:18:17Z Chaotic iak 3338 wikitext text/x-wiki Quoridor is an abstract board game for 2 or 4 players. Players move their pawns to reach the opposite side before their opponents; however, the defining quality is that players can place walls on the board that block all pawns, thus forcing pawns to navigate their way around the walls. == Start of the game == The board is 9x9 by size. Each player has one pawn, placed in the middle of their respective side. There are 20 walls, distributed equally to all players (10 each for two or 5 each for four). == Player's turn == In a player's turn, a player must do one of the following: * move their pawn, or * place a wall. === Moving a pawn === A player can move a pawn to an adjacent square in the four orthogonal directions (front, back, or sideways). The pawn may not cross past a wall. The pawn may never occupy the same square as an opponent's pawn; if an opponent pawn is adjacent, the player can jump over the opponent's pawn. If there is no wall, no board edge, and no other pawn behind the opponent's pawn, the jump must be straight (the player's pawn moves two squares in that direction). Otherwise, the jump must be diagonal (the player moves to the opponent, then moves sideways). Jumping is never mandatory. === Placing a wall === There are some walls in a player's inventory. Each wall are two squares long. A player may place a wall inside the board, between the squares. The wall may not jut out of the board, and it must be aligned with the grid, so that it blocks two pairs of adjacent squares. A wall blocks all pawns' movements; no pawn can jump over a wall. However, there must always be at least one path for each pawn to reach the opposite side; a wall may not be placed to completely isolate a pawn from their destination side. Note that walls are limited; if a player uses up all their walls, they can no longer place walls. == End of the game == If a player's pawn reaches any one of the nine squares on its destination side, opposite of the starting side, the player wins. f06a45df2c5eeb91919a5a8e2ee57f05979bc379 Reputation 0 17 1604 1514 2015-09-01T18:16:14Z Jerusus 7228 /* How to increase my reputation / what makes my reputation decrease ? */ wikitext text/x-wiki [[Category:Help]] == What is reputation ? == On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance. To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items: * Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png) * % of games you finished * % of games you finished with no clock penalties Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits. == How to increase my reputation / what makes my reputation decrease ? == At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks. * a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player. * a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player. You can only give a single thumb (green or red) to a single player. If your opinion changes you can click again on a thumb to reflect this change. As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended you leave the game or expel this player. By nature, opinions are subjective. There is nothing we can do for you if you receive a "red thumb" for an unfair reason. However, we know by experience that this system has a lot of advantages and generally gives relevant and useful information. == Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png == * Be polite! Say at least "hello" and "good luck" at the beginning of the game, and maybe "good game" ("gg") at the end of the game. * When you need some time to think, click on "I would like to think a little" link. * Always stay calm: it's a game. * Don't press your opponent to play if he has some time left. * If you really can't finish the game (this is not supposed to happen...), then say you are sorry and leave the game (don't wait to get expelled) to save your opponents time. Voluntarily disconnecting and conceding victory to the opponent does not cost you reputation like being expelled does. * Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give him a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!). * Be a good winner: if your opponent makes a mistake you can signal it to him, but avoid triumphalism and provocation. == What are the consequences of a bad reputation ? == A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you. It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents. 477990ea7d05c1df704bfe0f5b8f260c3d4d3795 Gamehelpcoltexpress 0 200 1605 2015-09-04T13:47:47Z Quinarbre 4507 Created page with "== Object of the game and sequence of play == To win, you must become the richest Bandit in the Old West. To reach this goal, you will try to get more Loot than your opponents..." wikitext text/x-wiki == Object of the game and sequence of play == To win, you must become the richest Bandit in the Old West. To reach this goal, you will try to get more Loot than your opponents...without being hit by too many bullets! The best shooter will receive the title of Gunslinger, worth $1000. There are five Rounds in a game. Each Round has two phases: * Phase 1 : Schemin'! The players play their Action cards into a common deck in the center of the table. * Phase 2 : Stealin'! The Action cards played during Phase 1 are performed. The game ends after five Rounds. Each player then adds up the value of the Loot tokens they have stolen. The Gunslinger prize is awarded to the player(s) who shot the most bullets. It is worth $1000. The richest player wins the game. In case of a tie, the winner is the tied player who has received the fewest Bullet cards from other players and Events during the game. === Starting a Round === At the beginning of a Round, each player shuffles their personal deck (made of the 10 Action cards of their colour) and draws six cards. These cards form that player's Hand. This Round card shows the number of turns (the number of Card icons) there will be during this phase. It also shows how the turns will go : * Standard turn - The Action cards must be played face-up during the current turn. * Tunnel - The Action cards must be played face-down during the current turn. * Speeding-Up - During the current turn, each player plays twice (taking 6 cards or playing two cards in a row or taking 3 cards and playing a card). * Switching - The current turn is played counter-clockwise, starting with the First Player. Some Round cards make Events happen. These Events always take place at the end of the Round, after Phase 2: Stealin'! See the tooltip of the Round card for more details. === Phase 1: Schemin'! === Starting with the First Player, each player plays their turn, followed by the next player in clockwise order. On his turn, a player has to: * either play an Action card face-up (unless otherwise specified) from his Hand to the common deck; * or take 3 additional cards from his deck and add them to his Hand. The Schemin'! phase ends when the number of turns indicated on the Round card has been completed. Any unplayed cards remaining in a player's Hand are placed back on the top of his personal deck. === Phase 2: Stealin'! === The deck of Action cards that had been created during the Schemin'! phase is turned over, without changing the order of the cards. The Bandits' Actions are performed, one by one, starting with the top card (i.e., in the order they have been played). Once performed, the Action card is given back to the player to whom it belongs. That player puts it back on his personal deck. Any Action programmed during the Schemin'! phase is now obligatory. During the Stealin'! phase, each player must use his action, if it is still possible. === Ending the Round === Each player shuffles all his cards (10 Action cards and any Bullet cards he has been hit with in previous Rounds). Then he places his deck to the right of his Character card. The player on the First Player's left becomes the new First Player. He puts the remaining Round cards in front of him. A new Round now begins. == The Action Cards == === Move === Move your Bandit: # from one Car to the next adjacent Car, forwards or backwards, if he is inside the Train; or # A distance ranging from one to three Cars (your choice), forwards or backwards, if he is on the roof. The Locomotive is considered to be a Car. You can be in it or on it. If you have plotted this Action, your Bandit cannot stay where he is: you must move him. === Floor Change === Switch the position of your Bandit from # The interior to the roof of the Car on which he's standing ; # or move his from the roof of the Car he's in to its interior. === Marshal === Move the Marshal inside the train a distance of one Car in the direction of your choice. (See "The Marshal", to find out what happens if the Marshal meets a Bandit). === Fire === Choose one of your opponents to be your target and give him one of your Bullet cards. The targeted player places the Bullet card he has received on his deck. You cannot target a Bandit who is on the same spot as you. # When you are inside the train, you can shoot a Bandit who is in the interior of an adjacent Car, either to the rear of your Car or ahead of it. Bandits who are more than one Car away cannot be shot. # When you are on the roof, however, you can shoot a Bandit who is in your Line of Sight and on the roof of any Car other than your own, regardless of the distance. A Bandit is in Line of Sight if there is no other Bandit between you and him. Two Bandits on the roof of the same Car are considered as being side by side, and not located one behind the other: you choose which one gets hit. If there is no target to be shot, keep your Bullet card: the Fire action will have no effect. If you successfully fire your 6 Bullet cards during the game, your Fire actions will have no further effect. === Robbery === Take the Loot token of your choice from the Car where you are currently located and place it face-down on your Character card. If your Bandit is on the roof of a Car, he cannot rob inside it, and vice versa. If there is no Loot where your Bandit is, then the Robbery action has no effect. === Punch === Choose a target among the Bandits who are on the same Car and same floor as you are. The targeted Bandit loses a Loot token if he has one: choose a Loot token from his Character card and place it on the floor where your Bandit pawn is located. If you choose a Purse token, you are not allowed to look at its value. Then, move the targeted Bandit to the same floor of an adjacent Car (either forwards or backwards, your choice in most of the Cars; backwards if you are in the Engine and forwards if you are in the Caboose). == The Marshal == Caution! When a Bandit enters a Car where the Marshal is, or when the Marshal enters a Car where Bandits are, they must escape up to the roof of the Car (even if they have just come down from there). A Bandit can never stay inside the Car where the Marshal is located. Additionally, each one of those Bandits immediately receives a Neutral Bullet card which must be placed on each player's personal deck. == Expert Variant == * At the end of the Schemin'! Phase, you are allowed to keep in your Hand the cards you are interested in holding for next Round. Discard all Bullet cards. Discard all Action cards that you are not interested in. * During the Stealin'! phase, place the performed Action cards you get back from the First Player on your discard deck. The Bullet cards you received that turn from your opponents, however, go on top of your draw deck, face-down. * At the beginning of each Round, draw cards from your draw deck and fill your Hand up to six cards. * Each time your draw deck is depleted and you have to draw cards, shuffle the discard deck to make a new draw deck. You can look through your discard at any time. == Set-Up for two players == There are four Cars, and each player chooses a team of two Characters. One Bandit pawn from each team is placed inside the two Cars at the rear of the train. Each Character of your team starts with a separate deck of six Bullet cards and a $250 Purse on each of them. From among the Action cards of each Character, every duplicate is discarded as well as the Marshal card from one of your Characters. You will have 11 cards remaining in your Hand: 2 Fire (1 for each Character), 2 Punch (1 for each Character), 2 Move (1 for each Character), 2 Floor Change (1 for each Character), 2 Robbery (1 for each Character) and 1 Marshal. Shuffle all of them to make your draw deck. Each player then plays with the mixed Action cards of the two Bandits. The game with two players is played with the Expert Variant described earlier. The goal of the game is to have the richest team at the end of the game. However, no one wins the title of Gunslinger in the 2-player game. When a Bandit is shot, the Bullet card is placed on the top of the player's draw deck. It may very well happen that a Bandit will inadvertently shoot his own teammate! (This summary is made of excerpts Ludonaute's rules for Colt Express.) d11eb5f874506111927456e84f85ba87e7072d91 1606 1605 2015-09-04T13:52:33Z Quinarbre 4507 wikitext text/x-wiki == Object of the game and sequence of play == To win, you must become the richest Bandit in the Old West. To reach this goal, you will try to get more Loot than your opponents...without being hit by too many bullets! The best shooter will receive the title of Gunslinger, worth $1000. There are five Rounds in a game. Each Round has two phases: * Phase 1 : Schemin'! The players play their Action cards into a common deck in the center of the table. * Phase 2 : Stealin'! The Action cards played during Phase 1 are performed. The game ends after five Rounds. Each player then adds up the value of the Loot tokens they have stolen. The Gunslinger prize is awarded to the player(s) who shot the most bullets. It is worth $1000. The richest player wins the game. In case of a tie, the winner is the tied player who has received the fewest Bullet cards from other players and Events during the game. === Starting a Round === At the beginning of a Round, each player shuffles their personal deck (made of the 10 Action cards of their colour) and draws six cards. These cards form that player's Hand. The Round card shows the number of turns (the number of Card icons) there will be during this phase. It also shows how the turns will go : * Standard turn - The Action cards must be played face-up during the current turn. * Tunnel - The Action cards must be played face-down during the current turn. * Speeding-Up - During the current turn, each player plays twice (taking 6 cards or playing two cards in a row or taking 3 cards and playing a card). * Switching - The current turn is played counter-clockwise, starting with the First Player. Some Round cards make Events happen. These Events always take place at the end of the Round, after Phase 2: Stealin'! See the tooltip of the Round card for more details. === Phase 1: Schemin'! === Starting with the First Player, each player plays their turn, followed by the next player in clockwise order. On his turn, a player has to: * either play an Action card face-up (unless otherwise specified) from his Hand to the common deck; * or take 3 additional cards from his deck and add them to his Hand. The Schemin'! phase ends when the number of turns indicated on the Round card has been completed. Any unplayed cards remaining in a player's Hand are placed back on the top of his personal deck. === Phase 2: Stealin'! === The deck of Action cards that had been created during the Schemin'! phase is turned over, without changing the order of the cards. The Bandits' Actions are performed, one by one, starting with the top card (i.e., in the order they have been played). Once performed, the Action card is given back to the player to whom it belongs. That player puts it back on his personal deck. Any Action programmed during the Schemin'! phase is now obligatory. During the Stealin'! phase, each player must use his action, if it is still possible. === Ending the Round === Each player shuffles all his cards (10 Action cards and any Bullet cards he has been hit with in previous Rounds). Then he places his deck to the right of his Character card. The player on the First Player's left becomes the new First Player and a new Round now begins. == The Action Cards == === Move === Move your Bandit: # from one Car to the next adjacent Car, forwards or backwards, if he is inside the Train; or # A distance ranging from one to three Cars (your choice), forwards or backwards, if he is on the roof. The Locomotive is considered to be a Car. You can be in it or on it. If you have plotted this Action, your Bandit cannot stay where he is: you must move him. === Floor Change === Switch the position of your Bandit from # The interior to the roof of the Car on which he's standing ; # or move his from the roof of the Car he's in to its interior. === Marshal === Move the Marshal inside the train a distance of one Car in the direction of your choice. (See "The Marshal", to find out what happens if the Marshal meets a Bandit). === Fire === Choose one of your opponents to be your target and give him one of your Bullet cards. The targeted player places the Bullet card he has received on his deck. You cannot target a Bandit who is on the same spot as you. # When you are inside the train, you can shoot a Bandit who is in the interior of an adjacent Car, either to the rear of your Car or ahead of it. Bandits who are more than one Car away cannot be shot. # When you are on the roof, however, you can shoot a Bandit who is in your Line of Sight and on the roof of any Car other than your own, regardless of the distance. A Bandit is in Line of Sight if there is no other Bandit between you and him. Two Bandits on the roof of the same Car are considered as being side by side, and not located one behind the other: you choose which one gets hit. If there is no target to be shot, keep your Bullet card: the Fire action will have no effect. If you successfully fire your 6 Bullet cards during the game, your Fire actions will have no further effect. === Robbery === Take the Loot token of your choice from the Car where you are currently located and place it face-down on your Character card. If your Bandit is on the roof of a Car, he cannot rob inside it, and vice versa. If there is no Loot where your Bandit is, then the Robbery action has no effect. === Punch === Choose a target among the Bandits who are on the same Car and same floor as you are. The targeted Bandit loses a Loot token if he has one: choose a Loot token from his Character card and place it on the floor where your Bandit pawn is located. If you choose a Purse token, you are not allowed to look at its value. Then, move the targeted Bandit to the same floor of an adjacent Car (either forwards or backwards, your choice in most of the Cars; backwards if you are in the Engine and forwards if you are in the Caboose). == The Marshal == Caution! When a Bandit enters a Car where the Marshal is, or when the Marshal enters a Car where Bandits are, they must escape up to the roof of the Car (even if they have just come down from there). A Bandit can never stay inside the Car where the Marshal is located. Additionally, each one of those Bandits immediately receives a Neutral Bullet card which must be placed on each player's personal deck. == Expert Variant == * At the end of the Schemin'! Phase, you are allowed to keep in your Hand the cards you are interested in holding for next Round. Discard all Bullet cards. Discard all Action cards that you are not interested in. * During the Stealin'! phase, place the performed Action cards you get back from the First Player on your discard deck. The Bullet cards you received that turn from your opponents, however, go on top of your draw deck, face-down. * At the beginning of each Round, draw cards from your draw deck and fill your Hand up to six cards. * Each time your draw deck is depleted and you have to draw cards, shuffle the discard deck to make a new draw deck. You can look through your discard at any time. == Set-Up for two players == There are four Cars, and each player chooses a team of two Characters. One Bandit pawn from each team is placed inside the two Cars at the rear of the train. Each Character of your team starts with a separate deck of six Bullet cards and a $250 Purse on each of them. From among the Action cards of each Character, every duplicate is discarded as well as the Marshal card from one of your Characters. You will have 11 cards remaining in your Hand: 2 Fire (1 for each Character), 2 Punch (1 for each Character), 2 Move (1 for each Character), 2 Floor Change (1 for each Character), 2 Robbery (1 for each Character) and 1 Marshal. Shuffle all of them to make your draw deck. Each player then plays with the mixed Action cards of the two Bandits. The game with two players is played with the Expert Variant described earlier. The goal of the game is to have the richest team at the end of the game. However, no one wins the title of Gunslinger in the 2-player game. When a Bandit is shot, the Bullet card is placed on the top of the player's draw deck. It may very well happen that a Bandit will inadvertently shoot his own teammate! ---- (This summary is made of excerpts Ludonaute's rules for Colt Express.) ef803cf1a59294f2a335a9607bbb233bf5e58dc5 1607 1606 2015-09-12T13:35:41Z Quinarbre 4507 wikitext text/x-wiki == Object of the game and sequence of play == To win, you must become the richest Bandit in the Old West. To reach this goal, you will try to get more Loot than your opponents...without being hit by too many bullets! The best shooter will receive the title of Gunslinger, worth $1000. There are five Rounds in a game. Each Round has two phases: * Phase 1 : Schemin'! The players play their Action cards into a common deck in the center of the table. * Phase 2 : Stealin'! The Action cards played during Phase 1 are performed. The game ends after five Rounds. Each player then adds up the value of the Loot tokens they have stolen. The Gunslinger prize is awarded to the player(s) who shot the most bullets. It is worth $1000. The richest player wins the game. In case of a tie, the winner is the tied player who has received the fewest Bullet cards from other players and Events during the game. === Starting a Round === At the beginning of a Round, each player shuffles their personal deck (made of the 10 Action cards of their colour) and draws six cards. These cards form that player's Hand. The Round card shows the number of turns (the number of Card icons) there will be during this phase. It also shows how the turns will go : * Standard turn - The Action cards must be played face-up during the current turn. * Tunnel - The Action cards must be played face-down during the current turn. * Speeding-Up - During the current turn, each player plays twice (taking 6 cards or playing two cards in a row or taking 3 cards and playing a card). * Switching - The current turn is played counter-clockwise, starting with the First Player. Some Round cards make Events happen. These Events always take place at the end of the Round, after Phase 2: Stealin'! See the tooltip of the Round card for more details. === Phase 1: Schemin'! === Starting with the First Player, each player plays their turn, followed by the next player in clockwise order. On his turn, a player has to: * either play an Action card face-up (unless otherwise specified) from his Hand to the common deck; * or take 3 additional cards from his deck and add them to his Hand. The Schemin'! phase ends when the number of turns indicated on the Round card has been completed. Any unplayed cards remaining in a player's Hand are placed back on the top of his personal deck. === Phase 2: Stealin'! === The deck of Action cards that had been created during the Schemin'! phase is turned over, without changing the order of the cards. The Bandits' Actions are performed, one by one, starting with the top card (i.e., in the order they have been played). Once performed, the Action card is given back to the player to whom it belongs. That player puts it back on his personal deck. Any Action programmed during the Schemin'! phase is now obligatory. During the Stealin'! phase, each player must use his action, if it is still possible. === Ending the Round === Each player shuffles all his cards (10 Action cards and any Bullet cards he has been hit with in previous Rounds). Then he places his deck to the right of his Character card. The player on the First Player's left becomes the new First Player and a new Round now begins. == The Action Cards == === Move === Move your Bandit: # from one Car to the next adjacent Car, forwards or backwards, if he is inside the Train; or # A distance ranging from one to three Cars (your choice), forwards or backwards, if he is on the roof. The Locomotive is considered to be a Car. You can be in it or on it. If you have plotted this Action, your Bandit cannot stay where he is: you must move him. === Floor Change === Switch the position of your Bandit from # The interior to the roof of the Car on which he's standing ; # or move his from the roof of the Car he's in to its interior. === The Marshal === Move the Marshal inside the train a distance of one Car in the direction of your choice. (See "The Marshal", to find out what happens if the Marshal meets a Bandit). === Fire === Choose one of your opponents to be your target and give him one of your Bullet cards. The targeted player places the Bullet card he has received on his deck. You cannot target a Bandit who is on the same spot as you. # When you are inside the train, you can shoot a Bandit who is in the interior of an adjacent Car, either to the rear of your Car or ahead of it. Bandits who are more than one Car away cannot be shot. # When you are on the roof, however, you can shoot a Bandit who is in your Line of Sight and on the roof of any Car other than your own, regardless of the distance. A Bandit is in Line of Sight if there is no other Bandit between you and him. Two Bandits on the roof of the same Car are considered as being side by side, and not located one behind the other: you choose which one gets hit. If there is no target to be shot, keep your Bullet card: the Fire action will have no effect. If you successfully fire your 6 Bullet cards during the game, your Fire actions will have no further effect. === Robbery === Take the Loot token of your choice from the Car where you are currently located and place it face-down on your Character card. If your Bandit is on the roof of a Car, he cannot rob inside it, and vice versa. If there is no Loot where your Bandit is, then the Robbery action has no effect. === Punch === Choose a target among the Bandits who are on the same Car and same floor as you are. The targeted Bandit loses a Loot token if he has one: choose a Loot token from his Character card and place it on the floor where your Bandit pawn is located. If you choose a Purse token, you are not allowed to look at its value. Then, move the targeted Bandit to the same floor of an adjacent Car (either forwards or backwards, your choice in most of the Cars; backwards if you are in the Engine and forwards if you are in the Caboose). == The Marshal == Caution! When a Bandit enters a Car where the Marshal is, or when the Marshal enters a Car where Bandits are, they must escape up to the roof of the Car (even if they have just come down from there). A Bandit can never stay inside the Car where the Marshal is located. Additionally, each one of those Bandits immediately receives a Neutral Bullet card which must be placed on each player's personal deck. == Expert Variant == * At the end of the Schemin'! Phase, you are allowed to keep in your Hand the cards you are interested in holding for next Round. Discard all Bullet cards. Discard all Action cards that you are not interested in. * During the Stealin'! phase, place the performed Action cards you get back from the First Player on your discard deck. The Bullet cards you received that turn from your opponents, however, go on top of your draw deck, face-down. * At the beginning of each Round, draw cards from your draw deck and fill your Hand up to six cards. * Each time your draw deck is depleted and you have to draw cards, shuffle the discard deck to make a new draw deck. You can look through your discard at any time. == Set-Up for two players == There are four Cars, and each player chooses a team of two Characters. One Bandit pawn from each team is placed inside the two Cars at the rear of the train. Each Character of your team starts with a separate deck of six Bullet cards and a $250 Purse on each of them. From among the Action cards of each Character, every duplicate is discarded as well as the Marshal card from one of your Characters. You will have 11 cards remaining in your Hand: 2 Fire (1 for each Character), 2 Punch (1 for each Character), 2 Move (1 for each Character), 2 Floor Change (1 for each Character), 2 Robbery (1 for each Character) and 1 Marshal. Shuffle all of them to make your draw deck. Each player then plays with the mixed Action cards of the two Bandits. The game with two players is played with the Expert Variant described earlier. The goal of the game is to have the richest team at the end of the game. However, no one wins the title of Gunslinger in the 2-player game. When a Bandit is shot, the Bullet card is placed on the top of the player's draw deck. It may very well happen that a Bandit will inadvertently shoot his own teammate! ---- (This summary is made of excerpts Ludonaute's rules for Colt Express.) b2e24704f3f7fcca57b726cd5345285f655506e4 Gamehelpyatzy 0 122 1608 1547 2015-09-12T22:42:18Z Mathgrant 3328 13 -> 14 wikitext text/x-wiki The game Yahtzee consists of 14 rounds. In each round, you roll 5 dice and then score the roll in a different category of your choice. During a round, you can roll the dice up to three times before scoring -- the initial roll (in which you must roll all the dice), plus two optional re-rolls of any or all dice. There are 14 scoring categories, and each must be used for one of the 14 rounds. This often results in a zero score for some categories. The 14 scoring categories are as follows: 1-6: There is one category for each number on the die. In these categories, the score is the sum of the pips on the dice of that number. For example, a roll of 1-1-2-5-5 could be scored as 2 points in the "ones" category, 2 points in the "twos" category, 10 points in the "fives" category, or 0 points in the "threes," "fours," or "sixes." If a player scores a total of at least 63 points across these six boxes, a bonus of 35 points is added. 7. Three-Of-A-Kind: At least three dice showing the same face -- Points equal the sum of all 5 dice (not just the 3 of a kind) 8. Four-Of-A-Kind: At least four dice showing the same face -- Points equal the sum of all 5 dice (not just the 4 of a kind) 9. Full House: A three-of-a-kind and a pair -- 25 points 10. Small Straight: Four sequential dice 1-2-3-4, 2-3-4-5, or 3-4-5-6) -- 30 points 11. Large Straight: Five sequential dice (1-2-3-4-5 or 2-3-4-5-6) -- 40 points 12. Yahtzee: All five dice showing the same face -- 50 points 13. Chance: Any combination -- points equal the sum of all 5 dice 14. Rigole: 4 times the same number and 1 time the opposite number on a dice (Ex. 1-1-1-1-6, 2-2-2-2-5, 3-3-3-3-4, 4-4-4-4-3, 5-5-5-5-2, 6-6-6-6-1) c45cb8943d40014d05b7eb4245bf464b7eb48c17 Gamehelpassyria 0 190 1612 1452 2015-09-15T18:24:04Z Senatorhung 4176 /* Summary of the game */ wikitext text/x-wiki == Summary of the game == '''GAME TURN'''<br> I - Farming:<br> : A) Sowing: the first player draws 5 Food cards twice and places them in order<br> : B) Harvest: in turn order, each player chooses one of the 2-card columns<br> : C) New turn order: depending on the columns that are chosen, a new turn order arises<br> II - Expansion: each player, in turn order, performs all of the actions below.<br> : A) New huts: the player places a number of huts corresponding to the value of the Expansion of the current turn<br> : B) Resupplying: using their cards, the player resupplies their huts<br> : C) Famine: unsupplied huts are removed from the board<br> : D) Wells: the player may place wells on the intersection of 3 hexagons on which they have huts<br> : E) Revenue & prestige: the player earns camels and scores points<br> III - Actions: each player, in turn order, spends their camels (totally or in part)<br> : A) Build / extend a ziggurat<br> : B) Create intrigue in Assur<br> : C) Make an offering to the gods<br> : D) Buy a Plow or Food card<br> End of turn: If this is not the end of a Reign, place a new Expansion card. Otherwise, a Flood takes place.<br> '''FLOOD'''<br> Flood Floods mark the end of a Reign. The first Reign ends after 2 game turns. The second and third Reigns end after 3 turns. :I) Flooding: each hut located on the river is removed<br> :II) Assur: the players count their influence and score points depending on the Expansion cards of the current Reign<br> :III) Dignitaries: the players score bonuses depending on the dignitaries on whose spaces they are placed<br> :IV) Offerings: the players multiply their position on the offerings tracks with the number of ziggurats they own on the board<br> :V) Next reign : place the Bonus card (4-players); place a new Expansion card.<br> '''END OF GAME'''<br> At the end of the 3rd Reign, players score 1 point per ziggurat tile, 1 point per Plow card and 1 point for each group of 2 remaining camels. d1f43c16f659cb99ae4b78deccf27b667c9ed3c9 Grade 0 30 1613 1596 2015-09-20T07:43:18Z Sayth 10124 /* All grades */ wikitext text/x-wiki Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. == All grades == * '''Mortal''': this is your grade when you just registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraphim can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherubim check that Seraphim are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. * '''Demon''': due to a major terms of use violation, this player is not allowed to do most of the things on the website during a period of time (or forever ......) :( a6416891313b530d3ea51d1d2fa2b6f27579b821 1614 1613 2015-09-20T07:45:35Z Sayth 10124 /* All grades */ wikitext text/x-wiki Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. --[[User:Sayth|Sayth]] 09:45, 20 September 2015 (CEST)== All grades ==--[[User:Sayth|Sayth]] 09:45, 20 September 2015 (CEST)''''''''Bold text'''''' ---- ''[[Media:Italic text]][[File:Example.jpg]]'' * '''Mortal''': this is your grade when you just registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraphim can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherubim check that Seraphim are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. * '''Demon''': due to a major terms of use violation, this player is not allowed to do most of the things on the website during a period of time (or forever ......) :( 18baffd8aaf5326bad5635242fd3c099e6850cbe Gamehelpnautilus 0 201 1615 2015-09-21T10:04:35Z Stst 2180 Created page with "== Object of the Game == During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigati..." wikitext text/x-wiki == Object of the Game == During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. == Setup == The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. The youngest player gets the Nemo token, thus becoming the first player of the round. == Preparation of the Round == Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. == Round Overview == To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. == End of the Round == The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. == End of Game and Scoring == The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. 7ba59aff6f99f5446c00c91957e1b43761e4c8db 1616 1615 2015-09-21T10:06:43Z Stst 2180 wikitext text/x-wiki === Object of the Game === During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. === Setup === The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. The youngest player gets the Nemo token, thus becoming the first player of the round. === Preparation of the Round === Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. === Round Overview === To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. === End of the Round === The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. === End of Game and Scoring === The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. 1a24c3c9f942b37f19313eb27df58201fb26f97e 1617 1616 2015-09-21T10:10:10Z Stst 2180 wikitext text/x-wiki ===Object of the Game=== During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. ===Setup=== The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. The youngest player gets the Nemo token, thus becoming the first player of the round. ===Preparation of the Round=== Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. ===Round Overview=== To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. ===End of the Round=== The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. ===End of Game and Scoring=== The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. 91d7184a4411f7637bd7dbac03c7b41ac0990300 1618 1617 2015-09-21T10:14:29Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. The youngest player gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. 6f64548cc4cd7b5affdb0400114eae6e95410f65 1619 1618 2015-09-21T10:15:11Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. The youngest player gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. b056552b301bff81294f6c62155a15b315569168 1620 1619 2015-09-21T10:18:50Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. 111 '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. The youngest player gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. 732459816d7def67dfaab9d45834c7c324bd0fae 1621 1620 2015-09-21T10:19:52Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. The youngest player gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. b056552b301bff81294f6c62155a15b315569168 1622 1621 2015-09-21T10:20:33Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. The youngest player gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. 38a2621b6fe683e4661e915bff6956a52764458c 1623 1622 2015-09-21T10:21:29Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. The youngest player gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. 198b0e8b4aa4af6fe70e4ae4cfecb5a52ac05e1e 1624 1623 2015-09-21T10:22:15Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. The youngest player gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. aa74fbe2555eb4738b1c7105bdc7475ce30f37a4 1625 1624 2015-09-21T13:27:13Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. The youngest player gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. '''Some Features of This Adaptation of the Game''' Duration of the game is 6 rounds by rules, but in this adaptation the game can proceed less 6 rounds. It will happen wnen one of players wins in 3 of 5 domains at end of a round. Player won domain at end a round if: 1. He has 4 or more score points in that domain. OR 2. He has 3 score points and domain card with -1 point(ink blot) already was played off (already in hand of one of players). It was done to end a game when one of players already won game. 12da18be582fe545b4499f22040ff66dcf0515d7 1626 1625 2015-09-21T13:27:46Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. The youngest player gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. '''Some Features of This Adaptation of the Game''' Duration of the game is 6 rounds by rules, but in this adaptation the game can proceed less 6 rounds. It will happen wnen one of players wins in 3 of 5 domains at end of a round. Player won domain at end a round if: 1. He has 4 or more score points in that domain. OR 2. He has 3 score points and domain card with -1 point(ink blot) already was played off (already in hand of one of players). It was done to end a game when one of players already won game. 4c7a4c9ad09f7f4fd1645c65b1b6a8097d66ac41 1627 1626 2015-09-21T18:49:57Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. The youngest player gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. '''Some Features of This Adaptation of the Game''' Duration of the game is 6 rounds by rules, but in this adaptation the game can proceed less 6 rounds. It will happen when one of players wins 3 of 5 domains at end of one of rounds. Player won the domain at end a round if: 1. He has gained 4 or more score points in the domain (at all previous rounds including current round). OR 2. He has gained 3 score points in the domain and domain card with -1 point(ink blot) already was played off (already in hand of one of players). It was done to end a game and not to play superfluous rounds when one of players already won a game. At end of game each player gets 1 victory point for each domain won (domain won by player when one of two conditions was executed, see above). Total score of a game is number of domain won by each player. d39645cc84680c635fe41295c74b57f18b2efbda 1628 1627 2015-09-21T18:53:18Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. The youngest player gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. '''Some Features of This Adaptation of the Game''' Duration of the game is 6 rounds by rules, but in this adaptation the game can proceed less 6 rounds. It will happen when one of players won 3 of 5 domains at end of one of rounds. Player won the domain at end a round if: 1. He has gained 4 or more score points in the domain (at all previous rounds including current round). OR 2. He has gained 3 score points in the domain and domain card with -1 point(ink blot) already was played off (already in hand of one of players). It was done to end a game and not to play superfluous rounds when one of players already won a game. At end of game each player gets 1 victory point for each domain won (domain won by player when one of two conditions was executed, see above). Total score of a game is number of domain won by each player. f8c17c679ba57cce803a2e9991fe5d83ed12eed2 1629 1628 2015-09-21T20:50:01Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. One of players gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. '''Some Features of This Adaptation of the Game''' Duration of the game is 6 rounds by rules, but in this adaptation the game can proceed less 6 rounds. It will happen when one of players won 3 of 5 domains at end of one of rounds. Player won the domain at end a round if: 1. He has gained 4 or more score points in the domain (at all previous rounds including current round). OR 2. He has gained 3 score points in the domain and domain card with -1 point(ink blot) already was played off (already in hand of one of players). It was done to end a game and not to play superfluous rounds when one of players already won a game. At end of game each player gets 1 victory point for each domain won (domain won by player when one of two conditions was executed, see above). Total score of a game is number of domain won by each player. 3953ae85f107095edd796e2adb6ab10cddfeae0b 1630 1629 2015-09-21T21:04:35Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. One of players gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. '''Some Features of This Adaptation of the Game''' Duration of the game is 6 rounds by rules, but in this adaptation the game can proceed less 6 rounds. It can happen when one of players has won 3 of 5 domains at end of one of rounds. Player won the domain at end a round if: 1. He has gained 4 or more score points in the domain (during all previous rounds including current round). OR 2. He has gained 3 score points in the domain and domain card with -1 point(ink blot) already was played off (already in hand of one of players). It was done to end a game and not to play superfluous rounds when one of players already won a game. At end of game each player gets 1 victory point for each domain won (domain won by player when one of two conditions was executed, see above). Total score of a game is number of domain won by each player. eb108152045e299e775cb431a1e43a8bfc7e6829 1631 1630 2015-09-22T05:20:20Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. One of players gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. '''Some Features of This Adaptation of the Game''' Duration of the game is 6 rounds by rules, but in this adaptation the game can proceed less 6 rounds. It can happen when one of players has won 3 of 5 domains at end of one of rounds. Player won the domain at end a round if: 1. He has gained 4 or more score points in the domain (during all previous rounds including current round). OR 2. He has gained 3 score points in the domain and domain card with -1 point(ink blot) already was played off (already in hand of one of players). It was done to end a game and not to play superfluous rounds when one of players already won a game. At end of game each player gets 1 victory point for each domain won (domain won by player when one of two conditions was executed, see above). Total score of a game is number of domains won by each player. 7bcce2ece9c789947597e613411f1cc0cb037b9d 1632 1631 2015-09-22T05:55:49Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. One of players gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. '''Some Features of This Adaptation of the Game''' Duration of the game is 6 rounds by rules, but in this adaptation the game can proceed less 6 rounds. It can happen when one of players has won 3 of 5 domains at end of one of rounds. Player won the domain at end a round if: 1. He has gained 4 or more score points in the domain (during all previous rounds including current round). OR 2. He has gained 3 score points in the domain and domain card with -1 point(ink blot) already was played off (already in hand of one of players). It was done to end a game and not to play superfluous rounds when one of players already won a game. At end of game each player gets 1 victory point for each domain won (domain won by player when one of two conditions was executed, see above). Total score of a game is number of domains won by each player. In addition... In rules there is the phrase: "The Diver card of value 1 (with a crab on it) always wins against the card of value 14, and only against that card." As I think following logic of the game, it's inaccuracy in rules and this card wins as against the Diver card of value 14 so and against the Fishbone special card (if it participates in current round). 073e8e0d519d4696352572cd38557c4f31bb0aea 1633 1632 2015-09-22T05:56:29Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. One of players gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. '''Some Features of This Adaptation of the Game''' Duration of the game is 6 rounds by rules, but in this adaptation the game can proceed less 6 rounds. It can happen when one of players has won 3 of 5 domains at end of one of rounds. Player won the domain at end a round if: 1. He has gained 4 or more score points in the domain (during all previous rounds including current round). OR 2. He has gained 3 score points in the domain and domain card with -1 point(ink blot) already was played off (already in hand of one of players). It was done to end a game and not to play superfluous rounds when one of players already won a game. At end of game each player gets 1 victory point for each domain won (domain won by player when one of two conditions was executed, see above). Total score of a game is number of domains won by each player. In addition... In rules there is the phrase: "The Diver card of value 1 (with a crab on it) always wins against the card of value 14, and only against that card". As I think following logic of the game, it's inaccuracy in rules and this card wins as against the Diver card of value 14 so and against the Fishbone special card (if it participates in current round). 7a2f08f8eed0b2de20b709da2c5b4bb0487726e3 1634 1633 2015-09-22T05:56:58Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. One of players gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. '''Some Features of This Adaptation of the Game''' Duration of the game is 6 rounds by rules, but in this adaptation the game can proceed less 6 rounds. It can happen when one of players has won 3 of 5 domains at end of one of rounds. Player won the domain at end a round if: 1. He has gained 4 or more score points in the domain (during all previous rounds including current round). OR 2. He has gained 3 score points in the domain and domain card with -1 point(ink blot) already was played off (already in hand of one of players). It was done to end a game and not to play superfluous rounds when one of players already won a game. At end of game each player gets 1 victory point for each domain won (domain won by player when one of two conditions was executed, see above). Total score of a game is number of domains won by each player. In addition... In rules there is the phrase: "The Diver card of value 1 (with a crab on it) always wins against the card of value 14, and only against that card". As I think following logic of the game, it's inaccuracy in rules and this card wins as against the Diver card of value 14 so and against the Fishbone special card (if it participates in current round). 67f4e9903e121224f064947eac44e4145f28d0f0 Gamehelpquantum 0 186 1635 1390 2015-09-25T15:34:02Z Clinton bolinger 10175 wikitext text/x-wiki Ship Abilities: Each type of ship has a unique special ability that can be used once per turn. * An individual ship die can only use ONE ability per turn, even if it changes number. * Using a ship ability does not count as an action (although maneuver and transport are used during a move action). * Ship abilities can only be used on your turn, and only by ships on the map. (Ships in the scrapyard and expansion ships can’t use abilities.) * You cannot change a ship number in the middle of moving that ship - for example, immediately before rolling for combat. '''1''' (Battlestation) STRIKE: attack space next to the battlestation Strike gives you a single free move/attack of 1 space that must include an attack. It is possible to move/attack normally and also use strike for a second attack on the same turn. '''2''' (Flagship) TRANSPORT: carry ship as you move Place one of your ships that is in any surrounding space on top of the flagship. Then use the flagship’s move action to move the flagship 1 or 2 spaces. Finally, place the transported ship in any empty surrounding space. A flagship cannot attack if it transports, but a transported ship CAN move and attack normally after it is dropped off. '''3''' (Destroyer) WARP: swap places with one of your ships on the map Warp does not count as the destroyer’s move '''4''' (Frigate) MODIFY: change to a 3 or 5 After you modify, you can’t use the ship’s new ability this turn, since modify was the ship’s ability use for the turn '''5''' (Interceptor) MANEUVER: travel diagonally Activating maneuver during your move action lets you go to any surrounding space as you move. This means you can travel diagonally as part or all of your movement. You CAN attack diagonally. '''6''' (Scout) FREE RECONFIGURE: re-roll the ship If you roll a 6, roll again until you get a new number. '''Void''' At the start of your turn, for each of your ship dice on the void map tile, you gain +1 research. Gaining research from the void does not use up any of your actions or special ability uses for your turn. Ships that earn you +1 research from the void can move and use special abilities normally that turn. 978de5c820ef12b884f450700b375eede4b68296 1636 1635 2015-09-25T15:34:36Z Clinton bolinger 10175 wikitext text/x-wiki Ship Abilities: Each type of ship has a unique special ability that can be used once per turn. * An individual ship die can only use ONE ability per turn, even if it changes number. * Using a ship ability does not count as an action (although maneuver and transport are used during a move action). * Ship abilities can only be used on your turn, and only by ships on the map. (Ships in the scrapyard and expansion ships can’t use abilities.) * You cannot change a ship number in the middle of moving that ship - for example, immediately before rolling for combat. '''1''' (Battlestation) STRIKE: attack space next to the battlestation Strike gives you a single free move/attack of 1 space that must include an attack. It is possible to move/attack normally and also use strike for a second attack on the same turn. '''2''' (Flagship) TRANSPORT: carry ship as you move Place one of your ships that is in any surrounding space on top of the flagship. Then use the flagship’s move action to move the flagship 1 or 2 spaces. Finally, place the transported ship in any empty surrounding space. A flagship cannot attack if it transports, but a transported ship CAN move and attack normally after it is dropped off. '''3''' (Destroyer) WARP: swap places with one of your ships on the map Warp does not count as the destroyer’s move '''4''' (Frigate) MODIFY: change to a 3 or 5 After you modify, you can’t use the ship’s new ability this turn, since modify was the ship’s ability use for the turn '''5''' (Interceptor) MANEUVER: travel diagonally Activating maneuver during your move action lets you go to any surrounding space as you move. This means you can travel diagonally as part or all of your movement. You CAN attack diagonally. '''6''' (Scout) FREE RECONFIGURE: re-roll the ship If you roll a 6, roll again until you get a new number. '''Void''' At the start of your turn, for each of your ship dice on the void map tile, you gain +1 research. Gaining research from the void does not use up any of your actions or special ability uses for your turn. Ships that earn you +1 research from the void can move and use special abilities normally that turn. 83e83ff9a53869d21e5f6db0e0a0c3f238249c0a Club Board Game Arena 0 8 1637 917 2015-09-27T21:53:34Z Platinum 3589 /* Is it mandatory to join the club ? */ wikitext text/x-wiki ==Why can't you just have a standard donation system where I can choose any money amount ?== With this "club" system, we try to highlight players who have supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time. Many websites are using a more classic approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena has chosen to set 3 fixed amounts for donations, in order to rely on a bigger number of small donors. ==Is it mandatory to join the club ?== Of course not. You can play for free with few limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra! You don't need statistics to play and have fun, do you? As a matter of fact, most players are not club members. ==What is a beginner account ? http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif == When you join Board Game Arena, you get a "beginner account" (http://en.boardgamearena.com/theme/img/accounttypes/beginner.gif) for 30 days. This beginner account allows you to view your own ELO ranking (http://en.boardgamearena.com/theme/img/common/rank.png) for each game. After 30 days, your account becomes a standard '''non-member''' account (http://en.boardgamearena.com/theme/img/accounttypes/free.gif). ==What becomes of the money ?== Board Game Arena's service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost). Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)... A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone ! 29e81484eef7ad3c90f843df9d54663f4b0d6bc5 Gamehelptock 0 202 1638 2015-09-30T02:51:38Z Fourmiant 10118 based off https://en.wikipedia.org/wiki/Tock wikitext text/x-wiki At the beginning of each round players are dealt 5 cards which they play in turns to move their tokens around the board. If at any time a token lands exactly on the field occupied by another token then the moved token replaces the resting one (which is placed back into the corresponding player's starting area). If a player on his turn has no cards he can play with his tokens (or which he can't play against the other players, like a 5, 10 or Queen in some variations) then he must discard his entire remaining hand and wait for the next hand to be dealt. A starter is a card that allows a player to move a new token to the starting field. Aces, Kings and Jokers are starters. A token at the starting field is immune to capture or swapping by an opponent, and additionally it creates a blockade. No players can pass a token that is on its starting field, either forward or backwards (with a 4). Cards Effects: Aces: +1 or starter Fours: -4 Fives: +5 to token owned by another player Sevens: 7 times +1 which can be split among all tokens Eights: +8 or use the shortcut if the tile Tens: +10 or force a player to discard a card randomly Jacks: +11 or swap two tokens Kings: +13 or starter To end the game, you need the exact count of fields to make it into the Goal, and you need to fill the goal from the top down. Tokens are not allowed to jump over other tokens within the goal field. Aside from a "Free for all" play style the game also supports a Two vs. Two vs. Two players, where Players on opposite sides of the board team up. 1fcb0f968e9a7564c794fc562fc0a48829e43ddb 1639 1638 2015-10-03T03:07:02Z Fourmiant 10118 wikitext text/x-wiki At the beginning of each round players are dealt 5 cards which they play in turns to move their tokens (or marbles) around the board. If at any time a token lands exactly on the field occupied by another token then the moved token replaces the resting one (which is placed back into the corresponding player's starting area). If a player on his turn has no cards he can play with his tokens (or which he can't play against the other players, like a 5, 10 or Queen in some variations) then he must discard his entire remaining hand and wait for the next hand to be dealt. A starter is a card that allows a player to move a new token to the starting field. Aces, Kings and Jokers are starters. A token at the starting field is immune to capture or swapping by an opponent, and additionally it creates a blockade. No players can pass a token that is on its starting field, either forward or backwards (with a 4). Cards Effects: Aces: +1 or starter Fours: -4 Fives: +5 to token owned by another player Sevens: 7 times +1 which can be split among all tokens Eights: +8 or use the shortcut if the tile Tens: +10 or force a player to discard a card randomly Jacks: +11 or swap two tokens Kings: +13 or starter To end the game, you need the exact count of fields to make it into the Home, and you need to fill the home from the top down. Tokens are not allowed to jump over other tokens within the home field. Aside from a "Free for all" play style the game also supports a Two vs. Two vs. Two players, where Players on opposite sides of the board team up. c13ee0f29d7d0afb06d69526a565c2d9a01055c7 1640 1639 2015-10-05T01:53:12Z Fourmiant 10118 wikitext text/x-wiki At the beginning of each round players are dealt 5 cards which they play in turns to move their tokens (or marbles) around the board. If at any time a token lands exactly on the field occupied by another token then the moved token replaces the resting one (which is placed back into the corresponding player's starting area). If a player on his turn has no cards he can play with his tokens (or which he can't play against the other players, like a 5, 10 or Queen in some variations) then he must discard his entire remaining hand and wait for the next hand to be dealt. A starter is a card that allows a player to move a new token to the starting field. Aces and Kings are starters. A token at the starting field is immune to capture or swapping by an opponent, and additionally it creates a blockade. No players can pass a token that is on its starting field, either forward or backwards (with a 4). Cards Effects: Aces: +1 or starter Fours: -4 Fives: +5 to token owned by another player Sevens: 7 times +1 which can be split among all tokens Tens: +10 or force a player to discard a card randomly Jacks: +11 or swap two tokens Kings: +13 or starter To end the game, you need the exact count of fields to make it into the Home, and you need to fill the home from the top down. Tokens are not allowed to jump over other tokens within the home field. Aside from a "Free for all" play style the game also supports a Two vs. Two vs. Two players, where Players on opposite sides of the board team up. 0b5d1719112be54604037b8b8c8350c8b6010e9c 1644 1640 2015-10-11T17:47:56Z Fourmiant 10118 wikitext text/x-wiki At the beginning of each round players are dealt 5 cards which they play in turns to move their tokens (or marbles) around the board. If at any time a token lands exactly on the field occupied by another token then the moved token replaces the resting one (which is placed back into the corresponding player's starting area). If a player on his turn has no cards he can play with his tokens (or which he can't play against the other players, like a 5 or 10 in some variations) then he must discard his entire remaining hand and wait for the next hand to be dealt. A starter is a card that allows a player to move a new token to the starting field. Aces and Kings are starters. A token at the starting field is immune to capture or swapping by an opponent, and additionally it creates a blockade. No players can pass a token that is on its starting field, either forward or backwards (with a 4). Cards Effects: Aces: +1 or starter Fours: -4 Fives: +5 to token owned by another player Sevens: 7 times +1 which can be split among all tokens Tens: +10 or force a player to discard a card randomly Jacks: +11 or swap two tokens Kings: +13 or starter To end the game, you need the exact count of fields to make it into the Home, and you need to fill the home from the top down. Tokens are not allowed to jump over other tokens within the home field. Aside from a "Free for all" play style the game also supports a Two vs. Two vs. Two players, where Players on opposite sides of the board team up. 6ef87d77f6b19564251f7f010917d580690ed3bb 1645 1644 2015-10-12T00:28:31Z Fourmiant 10118 wikitext text/x-wiki == Summary == Tock is a board game, similar to Pachisi, Ludo, Aggravation, "Jeu des petits chevaux" or Sorry!, in which players race their four tokens (or marbles) around the game board from start to finish—the objective being to be the first to take all of one's tokens "home". At the beginning of each round players are dealt 5 cards which they play in turns to move their tokens (or marbles) around the board. If at any time a token lands exactly on the field occupied by another token then the moved token replaces the resting one (which is placed back into the corresponding player's starting area). If a player on his turn has no cards he can play with his tokens (or which he can't play against the other players, like a 5 or 10 in some variations) then he must discard his entire remaining hand and wait for the next hand to be dealt. A starter is a card that allows a player to move a new token to the starting field. Aces and Kings are starters. A token at the starting field is immune to capture or swapping by an opponent, and additionally it creates a blockade. No players can pass a token that is on its starting field, either forward or backwards (with a 4). To end the game, you need the exact count of fields to make it into the Home, and you need to fill the home from the top down. Tokens are not allowed to jump over other tokens within the home field. == Cards Effects == Aces: +1 or starter Fours: -4 Fives: +5 to token owned by another player Sevens: 7 times +1 which can be split among all tokens Tens: +10 or force a player to discard a card randomly Jacks: +11 or swap two tokens Kings: +13 or starter == Variant == Aside from a "Free for all" play style the game also supports a Two vs. Two vs. Two (2v2v2) players, where Players on opposite sides of the board team up. 470f16221e0e363d2eae322463089630be1b363a 1646 1645 2015-10-12T00:29:25Z Fourmiant 10118 /* Cards Effects */ wikitext text/x-wiki == Summary == Tock is a board game, similar to Pachisi, Ludo, Aggravation, "Jeu des petits chevaux" or Sorry!, in which players race their four tokens (or marbles) around the game board from start to finish—the objective being to be the first to take all of one's tokens "home". At the beginning of each round players are dealt 5 cards which they play in turns to move their tokens (or marbles) around the board. If at any time a token lands exactly on the field occupied by another token then the moved token replaces the resting one (which is placed back into the corresponding player's starting area). If a player on his turn has no cards he can play with his tokens (or which he can't play against the other players, like a 5 or 10 in some variations) then he must discard his entire remaining hand and wait for the next hand to be dealt. A starter is a card that allows a player to move a new token to the starting field. Aces and Kings are starters. A token at the starting field is immune to capture or swapping by an opponent, and additionally it creates a blockade. No players can pass a token that is on its starting field, either forward or backwards (with a 4). To end the game, you need the exact count of fields to make it into the Home, and you need to fill the home from the top down. Tokens are not allowed to jump over other tokens within the home field. == Cards Effects == Aces: +1 or starter Fours: -4 Fives: +5 to token owned by another player Sevens: 7 times +1 which can be split among all tokens Tens: +10 or force a player to discard a card randomly Jacks: +11 or swap two tokens Kings: +13 or starter == Variant == Aside from a "Free for all" play style the game also supports a Two vs. Two vs. Two (2v2v2) players, where Players on opposite sides of the board team up. 5d6b6c376aad89901d4d8ad45a70fbc1fa0a3da8 1647 1646 2015-10-12T00:30:04Z Fourmiant 10118 /* Cards Effects */ wikitext text/x-wiki == Summary == Tock is a board game, similar to Pachisi, Ludo, Aggravation, "Jeu des petits chevaux" or Sorry!, in which players race their four tokens (or marbles) around the game board from start to finish—the objective being to be the first to take all of one's tokens "home". At the beginning of each round players are dealt 5 cards which they play in turns to move their tokens (or marbles) around the board. If at any time a token lands exactly on the field occupied by another token then the moved token replaces the resting one (which is placed back into the corresponding player's starting area). If a player on his turn has no cards he can play with his tokens (or which he can't play against the other players, like a 5 or 10 in some variations) then he must discard his entire remaining hand and wait for the next hand to be dealt. A starter is a card that allows a player to move a new token to the starting field. Aces and Kings are starters. A token at the starting field is immune to capture or swapping by an opponent, and additionally it creates a blockade. No players can pass a token that is on its starting field, either forward or backwards (with a 4). To end the game, you need the exact count of fields to make it into the Home, and you need to fill the home from the top down. Tokens are not allowed to jump over other tokens within the home field. == Cards Effects == - Aces: +1 or starter - Fours: -4 - Fives: +5 to token owned by another player - Sevens: 7 times +1 which can be split among all tokens - Tens: +10 or force a player to discard a card randomly - Jacks: +11 or swap two tokens - Kings: +13 or starter == Variant == Aside from a "Free for all" play style the game also supports a Two vs. Two vs. Two (2v2v2) players, where Players on opposite sides of the board team up. 6486f762bd46e842de5f1e42e6ee7d58392e0d8b 1648 1647 2015-10-12T00:30:32Z Fourmiant 10118 /* Cards Effects */ wikitext text/x-wiki == Summary == Tock is a board game, similar to Pachisi, Ludo, Aggravation, "Jeu des petits chevaux" or Sorry!, in which players race their four tokens (or marbles) around the game board from start to finish—the objective being to be the first to take all of one's tokens "home". At the beginning of each round players are dealt 5 cards which they play in turns to move their tokens (or marbles) around the board. If at any time a token lands exactly on the field occupied by another token then the moved token replaces the resting one (which is placed back into the corresponding player's starting area). If a player on his turn has no cards he can play with his tokens (or which he can't play against the other players, like a 5 or 10 in some variations) then he must discard his entire remaining hand and wait for the next hand to be dealt. A starter is a card that allows a player to move a new token to the starting field. Aces and Kings are starters. A token at the starting field is immune to capture or swapping by an opponent, and additionally it creates a blockade. No players can pass a token that is on its starting field, either forward or backwards (with a 4). To end the game, you need the exact count of fields to make it into the Home, and you need to fill the home from the top down. Tokens are not allowed to jump over other tokens within the home field. == Cards Effects == - Aces: +1 or starter. - Fours: -4. - Fives: +5 to token owned by another player. - Sevens: 7 times +1 which can be split among all tokens. - Tens: +10 or force a player to discard a card randomly. - Jacks: +11 or swap two tokens. - Kings: +13 or starter. == Variant == Aside from a "Free for all" play style the game also supports a Two vs. Two vs. Two (2v2v2) players, where Players on opposite sides of the board team up. cef95057243d55cec5ef9b1c55af9a05b9237281 Gamehelpspyrium 0 198 1641 1585 2015-10-08T20:01:14Z Rainn 5818 wikitext text/x-wiki Maximum number of workers: 7 When you reach 8 VP, you can get either an extra worker or £5. When you reach 20 VP, you get the bonus you didn't pick. a3efd4e2f245cdb820cae2b276231c126d92edc8 1642 1641 2015-10-08T20:06:07Z Rainn 5818 wikitext text/x-wiki Maximum number of workers: 7 Bonuses: * When you reach 8 VP, you can get either an extra worker or £5. * When you reach 20 VP, you get the bonus you didn't pick. When you replace a building with the same symbol, you save £3 on the price of the new building. 1c68164659ba4d3595a7419114d6afac8397bb40 Tutorial reversi 0 57 1643 1540 2015-10-11T12:32:55Z Gmc14 10318 wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for white and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('img/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just add "this.addTokenOnBoard( 2, 2, <your_player_id> )" in the "setup" Javascript method in reversi.js, and reload the page. '''Note''': ''your_player_id'' can be found by... ''someone who knows please edit'' A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "states.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where she is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where she is allowed to play. This method will be used in particular: * As we just said, to help the player to see where she can play. * When the player plays, to check if she has the right to play here. This is pure PHP programming here, and there are no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight the squares where the player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on the server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in stats.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 948bcb3b28af779b1854aa46ef85a0504e7bd506 Gamehelptashkalar 0 177 1649 1336 2015-10-12T20:20:59Z Danithaca 8886 wikitext text/x-wiki == Game forms == On Board Game Arena, Tash-Kalar may be played only by 2 players (now support up to 4 players), and in 2 distinct forms : - '''The High Form''': Players score points for tasks and for legendary pieces currently on the board. - '''Deathmatch Duel''': No tasks. Players score points for destroying enemy pieces, for summoning legendary beings, and when their opponent invokes a flare. The actual board game also features Deathmatch Melee for 3 or 4 players, and team play. == Setup == Each player draws 6 cards : 3 beings from his or her own deck, 2 legends, and 1 flare. In '''High Form''', 3 tasks are revealed that may be claimed, along with a fourth "next task". In '''Deathmatch''', the player who plays second puts one common piece of each color on the game board, on marked squares. == Game play == Players take turns in clockwise order, beginning with the starting player. Each turn, you have 2 actions. Exception: The starting player has only 1 action on his or her first turn. Possible actions: - '''Place 1 common piece''' of your color on any empty square. If you have none left to place, you begin this action by picking up 1 of your common or heroic pieces, then place it as a common piece. - '''Summon a being'''. (See below.) - '''Discard 1 being''' that you drew from your deck. If you do, you may also return one or more of your other cards to the bottoms of their decks. Actions can be done in any order. You can do more than one “place” or “summon” action per turn (but no more than one “discard” action). You have to use all your actions. You can invoke a flare (see below) before or after any action. Invoking a flare does not cost you an action. Finish your turn by drawing cards so that you end up with 3 beings from your deck, 2 legends, and 1 flare. If you draw the last card in your deck, you may end up with fewer than 3. '''High Form''': At the end of the turn, you may claim exactly 1 of the current tasks, if you meet its criteria. '''Deathmatch''': At the end of your turn, score points for destroyed enemy pieces: 2 points for legendary, 1 point for heroic, 1 point for each pair of common pieces. You get no points for destroying your own pieces. You get no points for an un- paired common piece. Also score 1 point each time you summon a legend. (Upgrading a heroic piece does not count as “summoning a legend”.) == Summoning a being == To summon a being, use 1 action and do the following: - '''Play the card''' from your hand and choose a square on the board where your pieces match the pattern on the card. The pattern can be rotated (by 90, 180, or 270 degrees). Mirror images and flips also count as a match. The pieces used to summon the being can be the same rank as those depicted in the pattern or higher rank. Empty squares are not important to the pattern. - '''Place a piece of the indicated rank''' (upper left corner of the card) on the square indicated by the white-framed square in the pattern. This square may be empty, unless the pattern says it must be occupied by one of your pieces. If the square is occupied by a piece of the same rank or lower, destroy that piece when you put the new piece on the square. If the square is occupied by a piece of higher rank, you cannot summon the being. If all your pieces of that type are already on the board, you may still be able to summon the being by picking up a piece that is not required for the pattern and use it as the new piece. - Once the new piece is on the board, '''resolve the effect''' printed on the card. - After resolving the effect, discard the card. == Invoking a flare == You can invoke a flare on your turn before or after any action. To invoke a flare, you must meet at least one of the criteria: - You meet the upper criterion if your opponent has '''that many more upgraded pieces''' (heroic and legendary) on the board than you. - You meet the lower criterion if your opponent has '''that many more pieces (total)''' on the board than you. If you meet the upper criterion, you resolve the upper effect. If you meet the lower criterion, you resolve the lower effect. If you meet both, you resolve the upper effect first, then the lower. Once the card has been resolved, discard it. == Resolving effects of beings and flares == No other action can be taken and no flare can be invoked until the entire effect of the card is resolved. Some parts of an effect may be optional: - May indicates that a certain part of an effect is optional. - Up to always includes 0. Any parts that are not specified as optional are mandatory. If an effect cannot be performed fully, do the parts that can be done. When a card uses its own name, it is referring to the piece on the board that represents the summoned being. '''Keywords''': - Upgraded piece: a heroic or legendary piece. - Non-legendary piece: a common or heroic piece. - Piece: If a piece is not specified as belonging to you or an opponent, then the effect includes any player's piece. - Marked space: a colored space in the pattern. If the text does not refer to marked spaces, the colored spaces in the pattern are just illustrational. - Adjacent square: one of eight squares sharing an edge (orthogonally adjacent) or a corner (diagonally adjacent) with a given square. If the given square is not specified, assume it is the square currently occupied by the newly summoned piece. - Distance: the shortest number of moves required to get from one square to another. For example, adjacent squares are at distance 1. - Move: A move is always onto an adjacent square. A move onto an occupied square destroys the piece that was there. - Standard move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Combat move: This type of move can be only onto an empty square or a square occupied by a piece of equal or lower rank. - Standard leap and combat leap: A leap is the same as a move, except the square doesn’t have to be adjacent. If not specified, a leap can be onto any square on the board. - Place: Like the “place” action. However, if there is no piece of the specified color and rank available, the piece cannot be placed. - Upgrade: Legendary pieces cannot be upgraded. To upgrade a common piece, flip it over. To upgrade a heroic piece, remove it and replace it with a legendary piece. If none is available, the heroic piece cannot be upgraded. - Downgrade: Common pieces cannot be downgraded. To downgrade a heroic piece, flip it over. To downgrade a legendary piece, replace it with a heroic piece. If none is available, the legendary piece cannot be downgraded. - Destroy: To destroy a piece, remove it from the board. - Convert: To convert an enemy piece, replace it with one of your pieces of the same rank (unless a different rank is specified). When keeping track of '''how many enemy pieces you destroyed''', count pieces you destroyed during summoning, pieces you destroyed with moves and leaps, pieces you destroyed with a “destroy” effect, and pieces you converted. Neither upgrading nor downgrading ever counts as destroying a piece. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. ---- These rules are extracted from CGE's full rules for Tash-Kalar. d414e3dd62d4470bbb1d03443209beb36673e2fa Faq 0 3 1650 1517 2015-10-21T22:58:21Z Mopie 10416 /* I joined a game. When does the game start? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) f7b96ae8b6845c94a1b0396068d734561118e1f3 1651 1650 2015-10-21T22:58:39Z Mopie 10416 /* What is the meaning of the small color circle next to players names? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and he has spent his reflexion time. Can someone wake him up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (he left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for his turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 409fbaae72d4378d39b903373b41ee25cf313bb1 Faq 0 3 1652 1651 2015-10-21T22:59:16Z Mopie 10416 /* What is the meaning of the icons next to players names? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and has spent their reflexion time. Can someone wake them up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for their turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as he needs to about the next move... well as long as he still has some time left on the game clock, that is. * Then you can ask this player to confirm that he is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left his computer temporarily. * If the player is not coming back, you can skip his turn as soon as his clock is negative. He will get a "leave" penalty and you will will "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) d0c6d3be05f690cd458ef94453aa40bcf26a66ac 1653 1652 2015-10-21T23:00:16Z Mopie 10416 /* A player has to make a move but he/she doesn't. What can I do? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and has spent their reflexion time. Can someone wake them up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for their turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as they need to about the next move... well as long as there is still some time left on the game clock, that is. * Then you can ask this player to confirm that he or she is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left the computer temporarily. * If the player is not coming back, you can skip their turn as soon as the clock is negative. This player will get a "leave" penalty and you will win "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give him a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from his profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 188019e75642cf0bf9d7ca18328008fed0327bd5 1654 1653 2015-10-21T23:00:37Z Mopie 10416 /* What if some player does something wrong? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from the whole world. A selection of various board games and card games is available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and has spent their reflexion time. Can someone wake them up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for their turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as they need to about the next move... well as long as there is still some time left on the game clock, that is. * Then you can ask this player to confirm that he or she is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left the computer temporarily. * If the player is not coming back, you can skip their turn as soon as the clock is negative. This player will get a "leave" penalty and you will win "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give them a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from their profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) aacaa422f217dede1dd9d4607fd60970e92c4c2c Gamehelpmetromaniab 0 203 1655 2015-10-26T01:29:42Z Fourmiant 10118 Created page with "== DESCRIPTION & OBJECTIVE == Each player represents a subway-building company, and will dig two subway lines across the city. The goal is to connect important destinations -..." wikitext text/x-wiki == DESCRIPTION & OBJECTIVE == Each player represents a subway-building company, and will dig two subway lines across the city. The goal is to connect important destinations - residential areas, commercial areas, and entertainment areas - and to provide them with subway stations. Take advantage of other players lines (for example, stations are built wherever two lines meet ; you can win points at the end by sharing the quickest trip), and try also to deroute or even block off your opponents at the right time, to keep them from well completing their lines! At the end of the game, the city government will run seven "test trips" between designated destinations, placed by the players themselves during the game. For each test trip, the fastest connection between the two points will be rewarded with Public Utility Points, and the player whose subways have the most points wins! == GAME COMPONENTS & SET UP == '''Game Board''' To set up the board, take the four border pieces and put them together. Take the six triangular "city" pieces, and arrange them randomly within the border. '''Counters''' Each player takes a set of counters of a particular color. Each has a score marker (showing a subway train), which is placed on the gameboard on the "0" space of the scoring track. Each player also has counters for two subway lines: one with a solid color, and another with a "striped" color. Each line should have a Start marker (white arrow), an End marker (black arrow), and eighteen triangular Tunnel counters. There are also twelve Destination markers. Each is marked with a letter (A-F), and is paired with another Destination marker. These will be the destinations that will be "tested" after the building phase is complete. The summary of these tests is in the upright corner of the board. Finally, there are thirty "station" markers, which are set by the side of the board, and are not controlled by any player. The map is made up of smaller triangles, which are either blank, have a destination symbol, or a lake/park. Along the edge of the city are white arrows indicating where a subway line starts, and black arrows indicating where they exit the city == THE COURSE OF THE GAME == '''Installation''' Take the destination markers and shuffle them letter-sidedown. With 4 players, each player takes one Residential, one Commercial, and one Entertainment Destination at random. That player then secretly looks at his markers. If two have the same letter, he puts one back and draws a new one until all three have different letters. When all the players have their three Destination markers, they flip them letter-side-up in front of them, visible for others. With 3 players, each player takes one more Destination marker. With 2 players, each player gets 6 Destination markers: one player gets the Destinations A,B,C,D,E,F shown on the left of the gameboard test Summary, the other player uses the ones on the right. '''Player turn''' The most "urbane" player begins. Play goes clockwise starting with the first player. On one's turn, the player MUST do one and only one of the following: - Dig 3 tunnels (to continue one or both of his lines) or - Build an intermediate station (on one of his lines) '''Starting a line''' Each player has two subway lines. On his first turn, a player must, of course, begin a subway line - but only one! A subway line must start from an empty space with a white arrow along the edge of the city. To start a line, place its first tunnel, topped with its "start" marker, in any of these spaces. Then continue normally the line in the city by digging the remaining tunnels. When you will begin your second subway line at any subsequent turn, it must start on one of the "opposite" edges from where your first line began. '''Digging tunnels''' Subway lines are built in the city by placing Tunnels in the triangular spaces. Only one tunnel may be placed in a space, and must conform to the following: - A line must always be built from its terminus; and never "branch off" - A line may not be continued with an acute angle. EXCEPTION: when a line terminates at a station, it may be built out from that station at any angle, even acute. - A line may never make a loop or double back on itself If you choose to dig tunnels on your turn, you MUST place 3 tunnels (unless it is only possible to place fewer). If you have two lines, you may distribute your 3 tunnels between them as you wish. '''Special areas''' The start or end spaces (with an arrow) along the edges of the city can only be used to start or end a line. Tunnel counters may never be placed on the park or the lake. When a player places a tunnel counter on top of a destination area, the player must place immediatly one of his Destination markers on that tunnel piece (of the appropriate type, of course), letter-side up. If a player does not have the appropriate marker, the player may not place that tunnel piece on the destination. Furthermore, each player may only place one destination marker per turn, and two destinations of the same letter cannot touch, either on an angle or on the side. '''Stations''' Most of the stations are created while digging tunnels. A station is immediately placed when: - The line being dug joins another line. In this case, a station is placed where the two lines meet up. - The line, which was running alongside another line, splits off from it. In this case, a station is placed where the line splits off. - When a line, running alongside another line, changes side, NO STATION is placed. The player scores 1 point for each destination area on the board that touches the station. He continues to dig tunnels after placing a station, if he still has some left to build. (i.e., building a station like this does not stop your tunneling.) '''Intermediate stations''' In lieu of digging tunnels, a player may use all his turn to place one station anywhere on one of his lines, between two preexisting stations. A starting or ending marker counts as a station for this purpose. Points are scored as for stations placed while digging tunnels. '''Ending lines''' A line ends on a space with a black arrow. The player digs his last tunnel on that space, topped with an "End Line" counter. A line may not end on the same edge as it started, nor on an adjoining edge to that "start edge," unless all the end spaces on the allowed sides are already taken. When a line ends, that player may immediately place an intermediate station anywhere on the line. However, once a line is completed (with this bonus station), the player may never place an intermediate station on that line again '''End of the building phase''' Players continue building until one of the following occurs: - A player has completed both of his lines - A player places the last station available - Five lines are either completed, or blocked and unable to be completed Note : a line is blocked if it can no longer be extended, typically because all the spaces at its end are already occupied, forbidden, or has run out of tunnels. Then all other players have one last turn to play. After, scoring begins. == THE SCORING PHASE == '''Lines scoring''' First, scores are adjusted as follows: - Players who completed both of their lines lose no points. - Players who completed only one line lose half their points (rounded down) - Players who completed none of their lines lose all their points. Adjust the scoring markers accordingly. '''Test trip scoring''' Each test trip runs between destination markers of the same letter: A to A, then B to B, and so on. You can see the summary of these trips in the upright corner of the board. For each trip, determine the shortest route: - a trip takes 1 minute to go from one station to another (no matter how many tunnel pieces are in between) - and 3 minutes to change from one line to another. A trip may have more than one fastest route. Each player who has a line making up part of the fastest route gets 3 points, plus a bonus of 3 points if he placed one of the destination markers (i.e., if the marker is on a tunnel piece of the player's color). A player may only get points once for each test, even if the player is involved in more than one route. Players who are not involved in the fastest route never get any point. '''Impossible trips''' Sometimes, a test run may be impossible. If that is the case, a city investigation takes place to determine the guilty party or parties: - If the destination marker was never placed on the board, the guilty party is the player who didn't place the marker. - If the marker was placed but nobody put a station touching it, the guilty party is the player who placed the destination. - If the markers were both placed, but no route exists between the two, both players who placed the markers are guilty. The guilty party or parties loose 6 points '''Final test''' The last test run is between the park and the lake. Determine the fastest route, as always. Each player involved in the fastest route gets 5 points. Important note : if your score goes beyond 20 points, move your marker normally, but place one of your tunnels near the 20 to show that. If your score goes below 0 point, place one of your tunnels near the 0. == THE WINNER == At the end of the game, the player with the most points is crowned King of the Subway - i.e., WINS. If there is a tie, the winner is the player who finished the most lines; if there is again a tie, the winner is the player who placed the most tunnels. If there is still a tie, litigation is the only possible solution. == SPECIAL RULES == Two players End of game: 3 lines finished and/or blocked ends the building phase. The other conditions still unchanged. Test trip scoring: when lines of both players are involded in the fastest route, the player who placed the most tunnels in this route only gets points. If there's a tie, nobody gets points. In case of an impossible trip, if both players are guilty, no one looses points. Three players End of game: 4 lines finished and/or blocked ends the building phase. The other conditions still unchanged. Test trip scoring: same as with four players. == VARIANTS == Unfair Municipality (3-4 players) Each player keeps his destination markers letter-side-down in front of him. The markers are only revealed when they are placed on a destination area in the city. No Corruption (3-4 players) Ah, everything is straight and clear… Because each player takes pre-etablished destination markers and keeps them in front of him, letter-face-up, of course! 4 players Player 1: A Residential, B Commercial, C Entertainment Player 2: D Residential, A Commercial, E Entertainment Player 3: F Residential, E Commercial, B Entertainment Player 4: C Residential, D Commercial, F Entertainment 3 players : Player 1: A & D Residential, B Commercial, C Entertainment Player 2: C Residential, A & E Commercial, F Entertainment Player 3: F Residential, D Commercial, B & E Entertainment Metromania Official Rulebook, Spiel or Face 1e1a6f0ab9b42dd1ea24b21cf052175a3979292d 1658 1655 2015-10-30T15:21:43Z Pikiou 1872 Special rule for 2 players from v2 of the rulebook won't be implemented wikitext text/x-wiki == DESCRIPTION & OBJECTIVE == Each player represents a subway-building company, and will dig two subway lines across the city. The goal is to connect important destinations - residential areas, commercial areas, and entertainment areas - and to provide them with subway stations. Take advantage of other players lines (for example, stations are built wherever two lines meet ; you can win points at the end by sharing the quickest trip), and try also to deroute or even block off your opponents at the right time, to keep them from well completing their lines! At the end of the game, the city government will run seven "test trips" between designated destinations, placed by the players themselves during the game. For each test trip, the fastest connection between the two points will be rewarded with Public Utility Points, and the player whose subways have the most points wins! == GAME COMPONENTS & SET UP == '''Game Board''' To set up the board, take the four border pieces and put them together. Take the six triangular "city" pieces, and arrange them randomly within the border. '''Counters''' Each player takes a set of counters of a particular color. Each has a score marker (showing a subway train), which is placed on the gameboard on the "0" space of the scoring track. Each player also has counters for two subway lines: one with a solid color, and another with a "striped" color. Each line should have a Start marker (white arrow), an End marker (black arrow), and eighteen triangular Tunnel counters. There are also twelve Destination markers. Each is marked with a letter (A-F), and is paired with another Destination marker. These will be the destinations that will be "tested" after the building phase is complete. The summary of these tests is in the upright corner of the board. Finally, there are thirty "station" markers, which are set by the side of the board, and are not controlled by any player. The map is made up of smaller triangles, which are either blank, have a destination symbol, or a lake/park. Along the edge of the city are white arrows indicating where a subway line starts, and black arrows indicating where they exit the city == THE COURSE OF THE GAME == '''Installation''' Take the destination markers and shuffle them letter-sidedown. With 4 players, each player takes one Residential, one Commercial, and one Entertainment Destination at random. That player then secretly looks at his markers. If two have the same letter, he puts one back and draws a new one until all three have different letters. When all the players have their three Destination markers, they flip them letter-side-up in front of them, visible for others. With 3 players, each player takes one more Destination marker. With 2 players, each player gets 6 Destination markers: one player gets the Destinations A,B,C,D,E,F shown on the left of the gameboard test Summary, the other player uses the ones on the right. '''Player turn''' The most "urbane" player begins. Play goes clockwise starting with the first player. On one's turn, the player MUST do one and only one of the following: - Dig 3 tunnels (to continue one or both of his lines) or - Build an intermediate station (on one of his lines) '''Starting a line''' Each player has two subway lines. On his first turn, a player must, of course, begin a subway line - but only one! A subway line must start from an empty space with a white arrow along the edge of the city. To start a line, place its first tunnel, topped with its "start" marker, in any of these spaces. Then continue normally the line in the city by digging the remaining tunnels. When you will begin your second subway line at any subsequent turn, it must start on one of the "opposite" edges from where your first line began. '''Digging tunnels''' Subway lines are built in the city by placing Tunnels in the triangular spaces. Only one tunnel may be placed in a space, and must conform to the following: - A line must always be built from its terminus; and never "branch off" - A line may not be continued with an acute angle. EXCEPTION: when a line terminates at a station, it may be built out from that station at any angle, even acute. - A line may never make a loop or double back on itself If you choose to dig tunnels on your turn, you MUST place 3 tunnels (unless it is only possible to place fewer). If you have two lines, you may distribute your 3 tunnels between them as you wish. '''Special areas''' The start or end spaces (with an arrow) along the edges of the city can only be used to start or end a line. Tunnel counters may never be placed on the park or the lake. When a player places a tunnel counter on top of a destination area, the player must place immediatly one of his Destination markers on that tunnel piece (of the appropriate type, of course), letter-side up. If a player does not have the appropriate marker, the player may not place that tunnel piece on the destination. Furthermore, each player may only place one destination marker per turn, and two destinations of the same letter cannot touch, either on an angle or on the side. '''Stations''' Most of the stations are created while digging tunnels. A station is immediately placed when: - The line being dug joins another line. In this case, a station is placed where the two lines meet up. - The line, which was running alongside another line, splits off from it. In this case, a station is placed where the line splits off. - When a line, running alongside another line, changes side, NO STATION is placed. The player scores 1 point for each destination area on the board that touches the station. He continues to dig tunnels after placing a station, if he still has some left to build. (i.e., building a station like this does not stop your tunneling.) '''Intermediate stations''' In lieu of digging tunnels, a player may use all his turn to place one station anywhere on one of his lines, between two preexisting stations. A starting or ending marker counts as a station for this purpose. Points are scored as for stations placed while digging tunnels. '''Ending lines''' A line ends on a space with a black arrow. The player digs his last tunnel on that space, topped with an "End Line" counter. A line may not end on the same edge as it started, nor on an adjoining edge to that "start edge," unless all the end spaces on the allowed sides are already taken. When a line ends, that player may immediately place an intermediate station anywhere on the line. However, once a line is completed (with this bonus station), the player may never place an intermediate station on that line again '''End of the building phase''' Players continue building until one of the following occurs: - A player has completed both of his lines - A player places the last station available - Five lines are either completed, or blocked and unable to be completed Note : a line is blocked if it can no longer be extended, typically because all the spaces at its end are already occupied, forbidden, or has run out of tunnels. Then all other players have one last turn to play. After, scoring begins. == THE SCORING PHASE == '''Lines scoring''' First, scores are adjusted as follows: - Players who completed both of their lines lose no points. - Players who completed only one line lose half their points (rounded down) - Players who completed none of their lines lose all their points. Adjust the scoring markers accordingly. '''Test trip scoring''' Each test trip runs between destination markers of the same letter: A to A, then B to B, and so on. You can see the summary of these trips in the upright corner of the board. For each trip, determine the shortest route: - a trip takes 1 minute to go from one station to another (no matter how many tunnel pieces are in between) - and 3 minutes to change from one line to another. A trip may have more than one fastest route. Each player who has a line making up part of the fastest route gets 3 points, plus a bonus of 3 points if he placed one of the destination markers (i.e., if the marker is on a tunnel piece of the player's color). A player may only get points once for each test, even if the player is involved in more than one route. Players who are not involved in the fastest route never get any point. '''Impossible trips''' Sometimes, a test run may be impossible. If that is the case, a city investigation takes place to determine the guilty party or parties: - If the destination marker was never placed on the board, the guilty party is the player who didn't place the marker. - If the marker was placed but nobody put a station touching it, the guilty party is the player who placed the destination. - If the markers were both placed, but no route exists between the two, both players who placed the markers are guilty. The guilty party or parties loose 6 points '''Final test''' The last test run is between the park and the lake. Determine the fastest route, as always. Each player involved in the fastest route gets 5 points. Important note : if your score goes beyond 20 points, move your marker normally, but place one of your tunnels near the 20 to show that. If your score goes below 0 point, place one of your tunnels near the 0. == THE WINNER == At the end of the game, the player with the most points is crowned King of the Subway - i.e., WINS. If there is a tie, the winner is the player who finished the most lines; if there is again a tie, the winner is the player who placed the most tunnels. If there is still a tie, litigation is the only possible solution. == SPECIAL RULES == Two players End of game: 3 lines finished and/or blocked ends the building phase. The other conditions still unchanged. Test trip scoring: the second version of the rules on this topic is not implemented on BGA. Three players End of game: 4 lines finished and/or blocked ends the building phase. The other conditions still unchanged. Test trip scoring: same as with four players. == VARIANTS == Unfair Municipality (3-4 players) Each player keeps his destination markers letter-side-down in front of him. The markers are only revealed when they are placed on a destination area in the city. No Corruption (3-4 players) Ah, everything is straight and clear… Because each player takes pre-etablished destination markers and keeps them in front of him, letter-face-up, of course! 4 players Player 1: A Residential, B Commercial, C Entertainment Player 2: D Residential, A Commercial, E Entertainment Player 3: F Residential, E Commercial, B Entertainment Player 4: C Residential, D Commercial, F Entertainment 3 players : Player 1: A & D Residential, B Commercial, C Entertainment Player 2: C Residential, A & E Commercial, F Entertainment Player 3: F Residential, D Commercial, B & E Entertainment Metromania Official Rulebook, Spiel or Face 17a0e67f5851ee37729b4d5518328e13a010ecd2 Main game logic: yourgamename.game.php 0 86 1656 1549 2015-10-27T11:01:06Z Ludovic 10347 wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 79 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. Notifications sent between the game start (setupNewGame) and the end of the "action" method of the first active state will never reach their destination. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array. Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. 660daee60d06a2b45dd181ccfe57539e6b29b223 1657 1656 2015-10-27T11:02:35Z Ludovic 10347 /* Accessing database */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 79 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. Notifications sent between the game start (setupNewGame) and the end of the "action" method of the first active state will never reach their destination. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array. Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. e9fd9b3eb4b0e5ff843b06d3a46f91fe95f6e16f Your game state machine: states.inc.php 0 90 1659 1597 2015-10-31T08:12:54Z Ludovic 10347 /* name */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. Note³: When a game is in prod and you change the ID of a state, all active games (including many turn based) will behave unpredictably. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. Warning! not put space in your name key. This could cause problems in some cases innatendus. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "args" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> === args === (optional) From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state. Example 1 : for Reversi, the list of possible moves during playerTurn state. Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor. Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them. In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them. Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array. Let's see a complete example using args with « Reversi » game : In states.inc.php, we specify some « args » argument for gamestate « playerTurn » : <pre> 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", <================================== HERE "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), </pre> It corresponds to a « argPlayerTurn » method in our PHP code (reversi.game.php): <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves() ); } </pre> Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn : <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> Note: you can also use values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above). Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn). Warning: the "args" method can be called before the "action" method so don't expect data modifications by the "action" method to be available in the "args" method! ==== Private infos in args ==== By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic. This is although possible to specify that some data should be sent to some specific players only: Example 1: send an information to active player(s) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private 'active' => array( // Using "active" keyword inside "_private", you select active player(s) 'somePrivateData' => self::getSomePrivateData() // will be send only to active player(s) ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> Inside the js file, these variables will be available through `args._private`. (e.g. `args._private.somePrivateData` -- it is not `args._private.active.somePrivateData` nor is it `args.somePrivateData`) Example 2: send an information to a specific player (<specific_player_id>) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private <specific_player_id> => array( // you select one specific player with its id 'somePrivateData' => self::getSomePrivateData() // will be send only to <specific_player_id> ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> IMPORTANT: in certain situation (ex: multipleactiveplayer game state) these "private data" features can have a big performance impact. Please do not use if not needed. === updateGameProgression === (optional) IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated. At least one of your game state (any of them) must specify updateGameProgression=>true. d0cf248caf499a883be6aca718417ab605ed608b 1660 1659 2015-10-31T08:15:27Z Ludovic 10347 /* name */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. Note³: When a game is in prod and you change the ID of a state, all active games (including many turn based) will behave unpredictably. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. Warning! Not put spaces in the name. This could cause problems in some cases innatendus. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "args" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> === args === (optional) From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state. Example 1 : for Reversi, the list of possible moves during playerTurn state. Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor. Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them. In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them. Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array. Let's see a complete example using args with « Reversi » game : In states.inc.php, we specify some « args » argument for gamestate « playerTurn » : <pre> 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", <================================== HERE "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), </pre> It corresponds to a « argPlayerTurn » method in our PHP code (reversi.game.php): <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves() ); } </pre> Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn : <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> Note: you can also use values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above). Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn). Warning: the "args" method can be called before the "action" method so don't expect data modifications by the "action" method to be available in the "args" method! ==== Private infos in args ==== By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic. This is although possible to specify that some data should be sent to some specific players only: Example 1: send an information to active player(s) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private 'active' => array( // Using "active" keyword inside "_private", you select active player(s) 'somePrivateData' => self::getSomePrivateData() // will be send only to active player(s) ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> Inside the js file, these variables will be available through `args._private`. (e.g. `args._private.somePrivateData` -- it is not `args._private.active.somePrivateData` nor is it `args.somePrivateData`) Example 2: send an information to a specific player (<specific_player_id>) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private <specific_player_id> => array( // you select one specific player with its id 'somePrivateData' => self::getSomePrivateData() // will be send only to <specific_player_id> ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> IMPORTANT: in certain situation (ex: multipleactiveplayer game state) these "private data" features can have a big performance impact. Please do not use if not needed. === updateGameProgression === (optional) IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated. At least one of your game state (any of them) must specify updateGameProgression=>true. 9fb6b98b0c816d022312af5020860f815c31bd82 1661 1660 2015-10-31T09:34:59Z Ludovic 10347 /* name */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. Note³: When a game is in prod and you change the ID of a state, all active games (including many turn based) will behave unpredictably. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. Warning! Not put spaces in the name. This could cause problems in some cases unexpected. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "args" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> === args === (optional) From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state. Example 1 : for Reversi, the list of possible moves during playerTurn state. Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor. Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them. In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them. Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array. Let's see a complete example using args with « Reversi » game : In states.inc.php, we specify some « args » argument for gamestate « playerTurn » : <pre> 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", <================================== HERE "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), </pre> It corresponds to a « argPlayerTurn » method in our PHP code (reversi.game.php): <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves() ); } </pre> Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn : <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> Note: you can also use values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above). Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn). Warning: the "args" method can be called before the "action" method so don't expect data modifications by the "action" method to be available in the "args" method! ==== Private infos in args ==== By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic. This is although possible to specify that some data should be sent to some specific players only: Example 1: send an information to active player(s) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private 'active' => array( // Using "active" keyword inside "_private", you select active player(s) 'somePrivateData' => self::getSomePrivateData() // will be send only to active player(s) ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> Inside the js file, these variables will be available through `args._private`. (e.g. `args._private.somePrivateData` -- it is not `args._private.active.somePrivateData` nor is it `args.somePrivateData`) Example 2: send an information to a specific player (<specific_player_id>) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private <specific_player_id> => array( // you select one specific player with its id 'somePrivateData' => self::getSomePrivateData() // will be send only to <specific_player_id> ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> IMPORTANT: in certain situation (ex: multipleactiveplayer game state) these "private data" features can have a big performance impact. Please do not use if not needed. === updateGameProgression === (optional) IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated. At least one of your game state (any of them) must specify updateGameProgression=>true. e42be1ee53f7425087e16303256d10223c1cb953 Game interface logic: yourgamename.js 0 88 1662 1136 2015-10-31T10:14:39Z Ludovic 10347 /* Access and manipulate the DOM */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; this.isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> The third parameter of dojo.place can take various interesting value. values possibles : "replace" : (see description above) "first" : Places the node as a child of the reference node. The node is placed as the first child. "last" : Places the node as a child of the reference node. The node is placed as the last child. "before" : places the node right before the reference node. "last (value by default) " : places the node right after the reference node. "only" : replaces all children of the reference node with the node. positif integer : This parameter can be a positif integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. See also full doc on dojo.place : [http://dojotoolkit.org/reference-guide/1.7/dojo/place.] Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''this.addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips '''this.removeTooltip( nodeId )''' Remove a tooltip from the DOM node. == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> You can also use three extra attributes in the parameter array for the notification: <pre> $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table, "header" => '<div>Some header</div>', "footer" => '<div>Some footer</div>', "closelabel" => clienttranslate( "Closing button label" ) ) ); </pre> *'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors) *'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names) *'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update. == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Gomoku example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. '''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 54fc55341c308685a186879f04778d76dbbde0f6 1663 1662 2015-10-31T10:15:47Z Ludovic 10347 /* Access and manipulate the DOM */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; this.isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> The third parameter of dojo.place can take various interesting value. values possibles : "replace" : (see description above). "first" : Places the node as a child of the reference node. The node is placed as the first child. "last" : Places the node as a child of the reference node. The node is placed as the last child. "before" : places the node right before the reference node. "last (value by default) " : places the node right after the reference node. "only" : replaces all children of the reference node with the node. positif integer : This parameter can be a positif integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. See also full doc on dojo.place : [http://dojotoolkit.org/reference-guide/1.7/dojo/place.] Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight: if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''this.addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips '''this.removeTooltip( nodeId )''' Remove a tooltip from the DOM node. == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> You can also use three extra attributes in the parameter array for the notification: <pre> $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table, "header" => '<div>Some header</div>', "footer" => '<div>Some footer</div>', "closelabel" => clienttranslate( "Closing button label" ) ) ); </pre> *'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors) *'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names) *'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update. == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Gomoku example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. '''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 5b250071d4dfa80ce242f3a398e1937033887541 1668 1663 2015-11-06T15:54:21Z Sourisdudesert 1 /* Players input */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; this.isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> The third parameter of dojo.place can take various interesting value. values possibles : "replace" : (see description above). "first" : Places the node as a child of the reference node. The node is placed as the first child. "last" : Places the node as a child of the reference node. The node is placed as the last child. "before" : places the node right before the reference node. "last (value by default) " : places the node right after the reference node. "only" : replaces all children of the reference node with the node. positif integer : This parameter can be a positif integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. See also full doc on dojo.place : [http://dojotoolkit.org/reference-guide/1.7/dojo/place.] Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight, (opt)color )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight (optional): if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. * color: could be '''blue''' (default), '''red''' or '''gray'''. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''this.addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips '''this.removeTooltip( nodeId )''' Remove a tooltip from the DOM node. == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> You can also use three extra attributes in the parameter array for the notification: <pre> $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table, "header" => '<div>Some header</div>', "footer" => '<div>Some footer</div>', "closelabel" => clienttranslate( "Closing button label" ) ) ); </pre> *'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors) *'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names) *'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update. == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Gomoku example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. '''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 1831da6c174dca5c1a3de84baa973a537a75d874 Gamehelpnautilus 0 201 1664 1634 2015-10-31T20:05:40Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. One of players gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. '''Game Option''' "Domain cards" option: - Visible: all collected domain cards by players are visible. - Hidden: collected cards by player are visible and collected cards by opponent are hidden. '''Some Features of This Adaptation of the Game''' Duration of the game is 6 rounds by rules, but in this adaptation the game can proceed less 6 rounds. It can happen when one of players has won 3 of 5 domains at end of one of rounds. Player won the domain at end a round if: 1. He has gained 4 or more score points in the domain (during all previous rounds including current round). OR 2. He has gained 3 score points in the domain and domain card with -1 point(ink blot) already was played off (already in hand of one of players). It was done to end a game and not to play superfluous rounds when one of players already won a game. At end of game each player gets 1 victory point for each domain won (domain won by player when one of two conditions was executed, see above). Total score of a game is number of domains won by each player. 7a3fc13f87de7cb4474c3fa2620dd723dfb00bb2 1665 1664 2015-10-31T20:06:22Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. One of players gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. '''Game Option''' "Domain cards" option: - Visible: all collected domain cards by players are visible. - Hidden: collected cards by player are visible and collected cards by opponent are hidden. '''Some Features of This Adaptation of the Game''' Duration of the game is 6 rounds by rules, but in this adaptation the game can proceed less 6 rounds. It can happen when one of players has won 3 of 5 domains at end of one of rounds. Player won the domain at end a round if: 1. He has gained 4 or more score points in the domain (during all previous rounds including current round). OR 2. He has gained 3 score points in the domain and domain card with -1 point(ink blot) already was played off (already in hand of one of players). It was done to end a game and not to play superfluous rounds when one of players already won a game. At end of game each player gets 1 victory point for each domain won (domain won by player when one of two conditions was executed, see above). Total score of a game is number of domains won by each player. 6837a78c3f88ca835d5fd5a0fa3da55d7be0ecc8 1666 1665 2015-10-31T20:07:59Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. One of players gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. '''Game Option''' "Domain cards" option: - Visible: all collected domain cards by players are visible (by default). - Hidden: collected cards by player are visible and collected cards by opponent are hidden. '''Some Features of This Adaptation of the Game''' Duration of the game is 6 rounds by rules, but in this adaptation the game can proceed less 6 rounds. It can happen when one of players has won 3 of 5 domains at end of one of rounds. Player won the domain at end a round if: 1. He has gained 4 or more score points in the domain (during all previous rounds including current round). OR 2. He has gained 3 score points in the domain and domain card with -1 point(ink blot) already was played off (already in hand of one of players). It was done to end a game and not to play superfluous rounds when one of players already won a game. At end of game each player gets 1 victory point for each domain won (domain won by player when one of two conditions was executed, see above). Total score of a game is number of domains won by each player. 4755718076c5bfb4ee4806cb13af44bf2a5e7d55 1667 1666 2015-11-06T05:46:38Z Stst 2180 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. One of players gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have horizontal or vertical arrows. When they are played, these cards cause a movement action. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. There is one exception to this rule: the Diver card of value 1 (with a crab on it) always wins against the card of value 14. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. '''Game Option''' "Domain cards" option: - Visible: all collected domain cards by players are visible (by default). - Hidden: collected cards by player are visible and collected cards by opponent are hidden. '''Some Features of This Adaptation of the Game''' Duration of the game is 6 rounds by rules, but in this adaptation the game can proceed less 6 rounds. It can happen when one of players has won 3 of 5 domains at end of one of rounds. Player won the domain at end a round if: 1. He has gained 4 or more score points in the domain (during all previous rounds including current round). OR 2. He has gained 3 score points in the domain and domain card with -1 point(ink blot) already was played off (already in hand of one of players). It was done to end a game and not to play superfluous rounds when one of players already won a game. At end of game each player gets 1 victory point for each domain won (domain won by player when one of two conditions was executed, see above). Total score of a game is number of domains won by each player. 9cb6ffad7f5e5c4fe81989620b45ac9e8f3e7dbd Gamehelpsaboteur 0 32 1669 1407 2015-11-08T21:44:42Z Cokethecat 10564 /* Rules summary */ wikitext text/x-wiki == Goal == Get as many gold nuggets as possible during the three rounds of the game. In order to do so, # if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards # if you are a '''saboteur''', you must, in association with other saboteurs, prevent the gold diggers to get to the treasure. Your role (gold digger or saboteur) will be randomly selected at the start of each round. == Rules summary == On your turn, you must click on a card from your hand to select it, then play this card or discard it. You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card. The cards are of several types: * 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card. * 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score). A player with a broken tool cannot play a Path card. * 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you. * 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know. Then click on "I have seen it" button at the top. * 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove. == Cards in play == * 44 'Path' cards * 9 'Sabotage' cards (three for each tool) * 6 'Repair a tool' cards (two for each tool) * 3 'Repair a tool among these two' cards (one for each combination of two tools) * 5 'Map' cards (one less than in the box set, as requested by the game author) * 3 'Rock fall' cards * 28 'Gold' cards ** 16 with one gold nugget ** 8 with two gold nuggets ** 4 with three gold nuggets == Roles == Roles are randomly selected among a set that depends upon the number of players: * with 3 players: 1 saboteur and 3 gold diggers * with 4 players: 1 saboteur and 4 gold diggers * with 5 players: 2 saboteurs and 4 gold diggers * with 6 players: 2 saboteurs and 5 gold diggers * with 7 players: 3 saboteurs and 5 gold diggers * with 8 players: 3 saboteurs and 6 gold diggers * with 9 players: 3 saboteurs and 7 gold diggers * with 10 players: 4 saboteurs and 7 gold diggers == Available variants == The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum! '''Have a good game !''' cefdd268fb6c8debf2d63e139acfbcae75840a9b Grade 0 30 1670 1614 2015-11-10T17:32:13Z Jmoney2cool 10585 wikitext text/x-wiki Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. --[[User:Sayth|Sayth]] 09:45, 20 September 2015 (CEST)== All grades ==--[[User:Sayth|Sayth]] 09:45, 20 September 2015 (CEST)''''''''Bold text'''''' ---- ''[[Media:Italic text]][[File:Example.jpg]]'' * '''Mortal''': this is your grade when you just registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). Don't worry! You'll be an Angel soon! * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraphim can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherubim check that Seraphim are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. * '''Demon''': due to a major terms of use violation, this player is not allowed to do most of the things on the website during a period of time (or forever ......) :( fb90b64acafd86ff343c1e34689f5354c8b0884b Gamehelpeightmastersrevenge 0 163 1671 1143 2015-11-16T21:50:02Z Vrmlghost 10600 /* Passive player (defender) */ wikitext text/x-wiki ===Overview and aim of the game=== 8 Masters’ Revenge is a fighting game for 1 to 4 players (only available for 2 players on BGA). You are a martial arts master and you want to beat your opponents, strike after strike. Your only weapons are your 2 hands, represented by the 2 cards you have in play. Find the weak point in your opponent’s guard to deal damage to him. As soon as his "health" marker reaches the last space of his life track (whose length depends of the number of players), he is out of the game. The last surviving player wins the fight. ====Turn break down==== =====Active player (attacker)===== The active player can choose to perform one of the following actions: Draw 2 cards (or 1 card if he or she already has 3 cards in hand due to having a handsize limit of 4 cards). After drawing cards the active player may move one token, in his or her area, to an adjacent field. '''Important: A damange token that lies on a emtpy field can only be placed on an adjacent empty field, and a damage token that lies on a card can only be placed on an adjacent card!''' ''Or'' Perform an attack! In order to do so the active player has to place a card from his/her hand in play. This card has to be put adjacent to the two cards already in play. The card that is not adjacent to the new card will be discarded and is the card that performs the attack. Now 5 steps take place: # Apply token effect (if any). # Check if the attack hits! An attack hits if the ''attacker’s attack value'' is '''exactly equal''' to the ''defender’s defense value''. (the attack value is the value created with the new card put in play; more below). # Deal damage if the attack hits. # Apply the effect of the discarded card. # Play an extra turn if a pair was formed with the new card (meaning that the center numbers are equal -> 1/1 2/2 3/3 4/4 5/5). During the extra turn a new attack can be launched or '''1''' card can be drawn. When no new pair is formed or when a card is drawn the turn is passed on the the second player. =====Passive player (defender)===== When the active player launches an attack, the passive player has 3 options if certain conditions are met. <ol> <li>Do nothing and take the blow (shouting: "''that doesn't hurt me!''") <li><b>Block the attack.</b> You can block an attack if you meet the following condition. <ol><li>If you have a card in play that has the same color as the card with which is attacked. (so you can block a yellow card with a yellow card). </li></ol> Blocking will reduce incoming dmg with 1. However, a card used for blocking stays in its blocking state, until it is discarded (used to attack), meaning you cannot use it a second time for blocking and you cannot form a pair with it. Most important if you're attacked a second time with a card of the same color and you still have the card in the blocking area '''you will suffer 2 additional damage'''.</li> <li><b>Counter the attack</b>. You can launch a counter attack on your opponents attack when you meet 2 conditions. <ol><li> you have in play a card with a dragon symbol</li> <li>you have a card in your hand with a dragon symbol</li></ol> If both conditions are met, you can form a dragon pair by playing the dragon card from your hand next to the dragon card you have in play. Be careful, as your opponent may perform a counter attack on your counter attack, if your opponent matches both conditions as well. When the attacker is not able to counter the counter attack his/her turn ends immediately and as such the effects from the card with which was attacked are not applied. (You can continue countering each other until one of you no longer has a card with a dragon symbol, to put in play). </li> </ol> =====Computation of defense and attack values===== The Attack value is equal to the sum of the numbers in the center of the couple of cards you have in play<br/> The Defense value is equal to the sum of the numbers of both ends of the couple of cards you have in play Example: you have a 2-4 and a 5-1 card in play. (2-4/5-1)<br/> Thus attack value = 9 (4+5)<br/> and defense value = 3 (2+1) b259b5f47eed01641693548d0119a45be3036ba3 Gamehelpinjawara 0 173 1672 1308 2015-11-20T17:40:28Z Shopliftersunite 2099 Section C "do nothing" is really unclear and badly explained, please rewrite this. What is meant with "Whilst there is a challenge that may be solved, we can skip this first phase and go straight for the challenge.?" Thank you for clearing this up. wikitext text/x-wiki == AIM OF THE GAME == The aim of the INJAWARA board game is to work in team cooperatively and contribute to solve at least 1 Challenge related to each Millennium Development Goal and 1 for each Region by moving the needed resources through the six regions and reply to questions related to the Challenges faced. The longer you ignore a problem, the more it will get worse! If a problem becomes too serious it will become impossible to solve it, and you will lose all. == THE GAME == The INJAWARA board game has no player turns, but in each round, all players, as a team, must decide the actions to do. How decisions are taken must be agreed by all players at the beginning of the game. Every round has three phases: === 1. USE OR MOVE RESOURCES (Optional) === Optionally, the team may make one of the following actions: move a resource to an adjacent region, use one unlocked resource power or simply do nothing in this phase. ==== A. MOVE A RESOURCE TO AN ADJACENT REGION ==== All regions are linked between them, indicated by the black arrows on the board. You can move one resource from one region to another linked region. ==== B. USE AN UNLOCKED RESOURCE POWER ==== If a resource has its power unlocked, you can use its power. Please note that after using the power of a resource you have to lock its power again and turn that resource upside down. All powers are the following: ===== Economic resources ===== Swap places of two resources on the board. Economic resources may be moved in this way as well. ===== Professionals ===== Move a resource to any region on the board. Professionals may be moved in this way as well. ===== Materials ===== Move towards higher score one box the score token of one of the following MDGS: 1, 2, 6, 7. ===== Politics ===== Move towards higher score one box the score token of one of the following MDGS: 3, 4, 5, 8. ===== Justice ===== You can discard a challenge token placed in any region, but it's not treated as solved. ===== Education ===== This is the only resource you have to use after having answered to the question. You can answer another questions, after failing a previous one, in order to solve a challenge. ==== C. DO NOTHING ==== Whilst there is a challenge that may be solved (see 2. Try to solve a challenge), we can skip this first phase and go straight for the challenge. Similarly, although there might not be any challenge that can be solved, it's possible for the team to pass in this phase and just go right to 3. A NEW CHALLENGE APPEARS. This is an actual valid option, but encourage the team to use it carefully. Maybe you can earn some more points by moving a resource or using a power, instead of letting the turn move on. === 2. TRY TO SOLVE A CHALLENGE (if it's possible) === Every challenge token has three data items: The region where it appears, the MDG affected by it, and the needed resource to solve it. If in the moment to start the turn or after using or moving resources, the convenient resource is on the same region than a challenge which needs it, the team may try to solve the challenge (see illustration). There is only one constraint: If you chose to move a resource at the beginning of the turn, you may only try to solve the challenges associated to that resource. This doesn't apply after using a power or if you decide not to move nor use a resource. If there is more than one challenge you can solve, YOU CANNOT SOLVE BOTH, but you have to choose which one you want to solve. So, grab the first question card from the question deck, and read out loud the question related to the MDG indicated by the challenge, and try to answer it working as a team. The right answers are in the reverse of the card, so try not to lift it up as others may see the answer. If you answer correctly, move forward the score marker associated to the MDG indicated by the challenge three boxes towards a higher score. It's not possible to move an score token beyond 100 points. If the score marker shows an X, turn it upside down to see the green tick. In the same manner, turn the region marker, where the challenge is located, upside down, if it wasn't showing the green tick yet. Likewise, if the resource was 'locked', turn it upside down, in order to unlock its power. The challenge token is discarded and place it in the discarded pile, marked with an X on the board. If you answer incorrectly, don't move any marker or token. In both cases, leave the question card on the discard pile, marked with an X, next to que question mark on the board. Place it with the questions facing up. === 3. A NEW CHALLENGE APPEARS === The challenge we left in the space marked by an eye on the board, is the next challenge that will appear in the game. Grab that challenge and place it on the region indicated by the leaf shape. In that moment, if in that region there was any other unsolved challenges, move one box towards a lower score, on the score board, all MDGs markers present in this region's challenges, without counting on the new challenge. ==== '-1' TOKEN ==== If the next challenge token is a '-1' one, check all unsolved challenges on the board and move one box towards a lower score, on the score board, all MDGs markers present. Only one box may be moved per MDG, so ignore other challenges that references the same MDG. In that moment, grab all tokens from discarded challenges pile (marked with an X on the board) and the '-1' token and put them back into the bag. Grab a new challenge token from the bag, randomly, and place it on the space marked with an eye. Now you know which is the challenge for the next round. == END OF THE GAME == There are two possible scenarios when the game ends: 1. ''The team loses the game'', if in any moment of the game, any MDG score marker reaches the skull. If you want to calculate your final score, see the "Scoring. If we lose." section below. 2. ''The team wins the game'', if in any moment of the game, all MDG score markers show the green tick and all region markers show the green tick as well. If this situation occurs in the middle of several challenges solving, you can end solving up all of them (and also use the Education power, if this is unlocked). == SCORING == === If we lose === If our team has lost the game, move towards a lower score, all MDG markers, 3 boxes. If any of the markers reaches the skull, it cannot be moved beyond. Then, sum up all the scores, knowing the skull scores 0 points. === If we won === Sum up all scores of all MDGs markers and this will be your final score. (On the score board you can see an aid for suming up to three markers on the same score box, on grey). 47cefdf94d4db45660789ad325197ecb49aeb3ff Gamehelpledernierpeuple 0 204 1673 2015-12-01T23:42:45Z Tyeor 3085 Created page with "In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards'..." wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== ''First'', you can (optional action) use a power card (those cards are collected Each card has a unique effect - see it by hovering the card in your hand. ''Secondly'', you have to chose between drawing 2 movement cards OR use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise) OR moving a meeple toward the card with the number indicated in the square. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or ofanother player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process or the second meeple cb87d2d9a53b49170e8a25c219291559ad59c745 1674 1673 2015-12-01T23:43:31Z Tyeor 3085 wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== ''First'', you can (optional action) use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. ''Secondly'', you have to chose between drawing 2 movement cards OR use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise) OR moving a meeple toward the card with the number indicated in the square. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or ofanother player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process or the second meeple 057bcbd301d5fdd174e70024b15af0c971d6f004 1675 1674 2015-12-01T23:44:08Z Tyeor 3085 wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== ''First'', you can (optional action) use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. ''Secondly'', you have to chose between drawing 2 movement cards OR use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise) OR moving a meeple toward the card with the number indicated in the square. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or ofanother player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process or the second meeple 96cd04f51694ed803c9e989d6133d569f962b42a 1676 1675 2015-12-01T23:44:54Z Tyeor 3085 wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== ''First'', you can (optional action) use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. ''Secondly'', you have to chose between drawing 2 movement cards OR use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise) OR moving a meeple toward the card with the number indicated in the square. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple 51a63ff8182f37f45a34ef300c53db306021ee2d 1677 1676 2015-12-01T23:45:20Z Tyeor 3085 wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== ''First'', you can (optional action) use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. ''Secondly'', you have to chose between drawing 2 movement cards OR use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise) OR moving a meeple toward the card with the number indicated in the square. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. eeceb8d48aa4a89ffc6b7583cd3edcb229780ba8 1678 1677 2015-12-02T17:44:05Z Tyeor 3085 wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== ''First'', you can (optional action) use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. ''Secondly'', you have to chose between drawing 2 movement cards OR use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise) OR moving a meeple toward the card with the number indicated in the square. Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. I fyes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. dbe68a928f53796bc4aae72b110aecf99e29f8af 1679 1678 2015-12-02T17:44:21Z Tyeor 3085 wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== ''First'', you can (optional action) use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. ''Secondly'', you have to chose between drawing 2 movement cards OR use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise) OR moving a meeple toward the card with the number indicated in the square. Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. f37524050ca05ed069f6e4e200355b4e30a0f174 1680 1679 2015-12-02T17:44:47Z Tyeor 3085 wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== ''First'', you can (optional action) use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. ''Secondly'', you have to chose between drawing 2 movement cards OR use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise) OR moving a meeple toward the card with the number indicated in the square. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. 66798fe4c9b7dc7235b781e40eff45351af28d3a 1681 1680 2015-12-02T17:45:51Z Tyeor 3085 wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== ''First'', you can (optional action) use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. ''Secondly'', you have to chose between drawing 2 movement cards OR use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise) OR moving a meeple toward the card with the number indicated in the square. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. 2bcc3fdc32c3b3bcce1a3405dc8ca4d61547939e 1682 1681 2015-12-02T17:47:03Z Tyeor 3085 wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== ''First'', you can (optional action) use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. ''Secondly'', you have to chose between drawing 2 movement cards OR use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise) OR moving a meeple toward the card with the number indicated in the square. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. 95f2a35003318a086dc63f7e99f8479529b22cce 1683 1682 2015-12-04T02:52:52Z Senatorhung 4176 wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== ''First'', you can (optional action) use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. ''Secondly'', you have to chose between drawing 2 movement cards OR use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise) OR moving a meeple toward the card with the number indicated in the square. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Cards == (Google translated from: http://www.ledernierpeuple.com/regles.php#but_du_jeu ... card names may not match BGA) Strength: Win a token "2 VP" of the bank. Care: Win a token "1 PV" of the bank. Thief: Steal 1 VP to the player of your choice (if not token "1 PV", he must make change with the bank to give you that PV). Bandit: Steal a card at random from the hand of the player of your choice. Hex: The player must make your choice (if possible) 1 VP at the bank (if not token "1 PV", he must make change with the bank to make this PV) . Black Magic: Randomly select a card hand of the player of your choice that you discard without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Swap: Swap instead of one of your pawns with the player of your choice. (Do not solve the possible action generated by this new configuration.) Chance: Draw a card "displacement" and a map "power" and add them to your hand. The next card is to play out of turn when is the target of an attack or card "power" (except "Swap"). Defence: You do not suffer the effect and the attackers or do not earn PV. Moreover, in case of attack countered attackers pawns are still repositioned. cae3640911942c6755a8e3e7ac5ebd478cbfd6a8 1684 1683 2015-12-04T02:54:45Z Senatorhung 4176 /* Power Cards */ wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== ''First'', you can (optional action) use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. ''Secondly'', you have to chose between drawing 2 movement cards OR use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise) OR moving a meeple toward the card with the number indicated in the square. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Cards == (Google translated from: http://www.ledernierpeuple.com/regles.php#but_du_jeu ... card names may not match BGA) Strength: Win a token "2 VP" of the bank. Care: Win a token "1 VP" of the bank. Thief: Steal 1 VP to the player of your choice (if not token "1 VP", he must make change with the bank to give you that VP). Bandit: Steal a card at random from the hand of the player of your choice. Hex: The player must make your choice (if possible) 1 VP at the bank (if not token "1 VP", he must make change with the bank to make this V) . P Black Magic: Randomly select a card hand of the player of your choice that you discard without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Swap: Swap instead of one of your pawns with the player of your choice. (Do not solve the possible action generated by this new configuration.) Chance: Draw a card "displacement" and a map "power" and add them to your hand. The next card is to play out of turn when is the target of an attack or card "power" (except "Swap"). Defence: You do not suffer the effect and the attackers or do not earn VP. Moreover, in case of attack countered attackers pawns are still repositioned. 98136fd52321b18c5ec2f804f1bc440742f08ddd 1685 1684 2015-12-04T02:55:19Z Senatorhung 4176 /* Power Cards */ wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== ''First'', you can (optional action) use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. ''Secondly'', you have to chose between drawing 2 movement cards OR use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise) OR moving a meeple toward the card with the number indicated in the square. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Cards == (Google translated from: http://www.ledernierpeuple.com/regles.php#but_du_jeu ... card names may not match BGA) Strength: Win a token "2 VP" of the bank. Care: Win a token "1 VP" of the bank. Thief: Steal 1 VP to the player of your choice (if not token "1 VP", he must make change with the bank to give you that VP). Bandit: Steal a card at random from the hand of the player of your choice. Hex: The player must make your choice (if possible) 1 VP at the bank (if not token "1 VP", he must make change with the bank to make this VP). Black Magic: Randomly select a card hand of the player of your choice that you discard without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Swap: Swap instead of one of your pawns with the player of your choice. (Do not solve the possible action generated by this new configuration.) Chance: Draw a card "displacement" and a map "power" and add them to your hand. The next card is to play out of turn when is the target of an attack or card "power" (except "Swap"). Defence: You do not suffer the effect and the attackers or do not earn VP. Moreover, in case of attack countered attackers pawns are still repositioned. df2d46a81f56462aa4dcb66795dd7f6c6d8247df 1686 1685 2015-12-04T02:59:36Z Senatorhung 4176 /* Power Cards */ wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== ''First'', you can (optional action) use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. ''Secondly'', you have to chose between drawing 2 movement cards OR use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise) OR moving a meeple toward the card with the number indicated in the square. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Cards == (Card names may not match BGA exactly since Google translate used: http://www.ledernierpeuple.com/regles.php#but_du_jeu) Strength: Win a token "2 VP" of the bank. Care: Win a token "1 VP" of the bank. Thief: Steal 1 VP to the player of your choice (if not token "1 VP", he must make change with the bank to give you that VP). Bandit: Steal a card at random from the hand of the player of your choice. Hex: The player must make your choice (if possible) 1 VP at the bank (if not token "1 VP", he must make change with the bank to make this VP). Black Magic: Randomly select from a card from an opponent's hand and discard the card without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Swap: Swap one of your pawns with the player of your choice. (Do not solve the possible action generated by this new configuration.) Chance: Draw a card "displacement" and a card "power" and add them to your hand. The next card is to play out of turn when is the target of an attack or card "power" (except "Swap"). Defence: You do not suffer the effect and the attackers or do not earn VP. Moreover, in case of attack countered attackers pawns are still repositioned. fa8220dc8d7a28770cd2ae6cd4b8be2a04b8f987 1687 1686 2015-12-04T03:00:16Z Senatorhung 4176 /* Power Cards */ wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== ''First'', you can (optional action) use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. ''Secondly'', you have to chose between drawing 2 movement cards OR use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise) OR moving a meeple toward the card with the number indicated in the square. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Cards == (Card names may not match BGA exactly since Google translate used: http://www.ledernierpeuple.com/regles.php#but_du_jeu) Strength: Win a token "2 VP" of the bank. Care: Win a token "1 VP" of the bank. Thief: Steal 1 VP to the player of your choice (if not token "1 VP", he must make change with the bank to give you that VP). Bandit: Steal a card at random from the hand of the player of your choice. Hex: The player must make your choice (if possible) 1 VP at the bank (if not token "1 VP", he must make change with the bank to make this VP). Black Magic: Randomly select from a card from an opponent's hand and discard the card without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Swap: Swap one of your pawns with the player of your choice. (Do not solve the possible action generated by this new configuration.) Chance: Draw 1 movement card and 1 power card and add them to your hand. The next card is to play out of turn when is the target of an attack or card "power" (except "Swap"). Defence: You do not suffer the effect and the attackers or do not earn VP. Moreover, in case of attack countered attackers pawns are still repositioned. 5ae6a2d4a37ccfe77f165afb2434d57ca5c7395f 1688 1687 2015-12-04T03:03:51Z Senatorhung 4176 /* A turn */ wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== === Power Cards Phase (optional) === You can use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. See section below for more details on each specific power card. === Movement Phase === You have to chose between: (a) drawing 2 movement cards; OR (b) use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : (a) moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise); OR (b) moving a meeple toward the card with the number indicated in the square. Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). == Resolving attacks and supplies == ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. == Redeployment == If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Cards == (Card names may not match BGA exactly since Google translate used: http://www.ledernierpeuple.com/regles.php#but_du_jeu) Strength: Win a token "2 VP" of the bank. Care: Win a token "1 VP" of the bank. Thief: Steal 1 VP to the player of your choice (if not token "1 VP", he must make change with the bank to give you that VP). Bandit: Steal a card at random from the hand of the player of your choice. Hex: The player must make your choice (if possible) 1 VP at the bank (if not token "1 VP", he must make change with the bank to make this VP). Black Magic: Randomly select from a card from an opponent's hand and discard the card without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Swap: Swap one of your pawns with the player of your choice. (Do not solve the possible action generated by this new configuration.) Chance: Draw 1 movement card and 1 power card and add them to your hand. The next card is to play out of turn when is the target of an attack or card "power" (except "Swap"). Defence: You do not suffer the effect and the attackers or do not earn VP. Moreover, in case of attack countered attackers pawns are still repositioned. 447c45ba1beaad244e78ae95c87449d58dff7da8 1689 1688 2015-12-04T03:05:40Z Senatorhung 4176 wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== === Power Cards Phase (optional) === You can use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. See section below for more details on each specific power card. === Movement Phase === You have to chose between: (a) drawing 2 movement cards; OR (b) use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : (a) moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise); OR (b) moving a meeple toward the card with the number indicated in the square. Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. === Resolving attacks and supplies === ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. === Redeployment === If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Cards == (Card names may not match BGA exactly since Google translate used: http://www.ledernierpeuple.com/regles.php#but_du_jeu) Strength: Win a token "2 VP" of the bank. Care: Win a token "1 VP" of the bank. Thief: Steal 1 VP to the player of your choice (if not token "1 VP", he must make change with the bank to give you that VP). Bandit: Steal a card at random from the hand of the player of your choice. Hex: The player must make your choice (if possible) 1 VP at the bank (if not token "1 VP", he must make change with the bank to make this VP). Black Magic: Randomly select from a card from an opponent's hand and discard the card without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Swap: Swap one of your pawns with the player of your choice. (Do not solve the possible action generated by this new configuration.) Chance: Draw 1 movement card and 1 power card and add them to your hand. The next card is to play out of turn when is the target of an attack or card "power" (except "Swap"). Defence: You do not suffer the effect and the attackers or do not earn VP. Moreover, in case of attack countered attackers pawns are still repositioned. 8c1f9038318dd5ab891db054fd0ed1365b5afeb2 1690 1689 2015-12-04T03:06:12Z Senatorhung 4176 /* Power Cards */ wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== === Power Cards Phase (optional) === You can use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. See section below for more details on each specific power card. === Movement Phase === You have to chose between: (a) drawing 2 movement cards; OR (b) use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : (a) moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise); OR (b) moving a meeple toward the card with the number indicated in the square. Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. === Resolving attacks and supplies === ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. === Redeployment === If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Card Details == (Card names may not match BGA exactly since Google translate used: http://www.ledernierpeuple.com/regles.php#but_du_jeu) Strength: Win a token "2 VP" of the bank. Care: Win a token "1 VP" of the bank. Thief: Steal 1 VP to the player of your choice (if not token "1 VP", he must make change with the bank to give you that VP). Bandit: Steal a card at random from the hand of the player of your choice. Hex: The player must make your choice (if possible) 1 VP at the bank (if not token "1 VP", he must make change with the bank to make this VP). Black Magic: Randomly select from a card from an opponent's hand and discard the card without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Swap: Swap one of your pawns with the player of your choice. (Do not solve the possible action generated by this new configuration.) Chance: Draw 1 movement card and 1 power card and add them to your hand. The next card is to play out of turn when is the target of an attack or card "power" (except "Swap"). Defence: You do not suffer the effect and the attackers or do not earn VP. Moreover, in case of attack countered attackers pawns are still repositioned. ff73e01b507dbbd5760dd0fa4c112eaeb38e0f6d 1691 1690 2015-12-04T03:13:53Z Senatorhung 4176 /* Power Card Details */ wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== === Power Cards Phase (optional) === You can use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. See section below for more details on each specific power card. === Movement Phase === You have to chose between: (a) drawing 2 movement cards; OR (b) use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : (a) moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise); OR (b) moving a meeple toward the card with the number indicated in the square. Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. === Resolving attacks and supplies === ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. === Redeployment === If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Card Details == (Card names may not match BGA exactly since Google translate used: http://www.ledernierpeuple.com/regles.php#but_du_jeu) === Played During Power Card Phase === Strength: Win a token "2 VP" of the bank. Care: Win a token "1 VP" of the bank. Thief: Steal 1 VP to the player of your choice (if not token "1 VP", he must make change with the bank to give you that VP). Bandit: Steal a card at random from the hand of the player of your choice. Hex: The player must make your choice (if possible) 1 VP at the bank (if not token "1 VP", he must make change with the bank to make this VP). Black Magic: Randomly select from a card from an opponent's hand and discard the card without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Swap: Swap one of your pawns with the player of your choice. (Do not solve the possible action generated by this new configuration.) Chance: Draw 1 movement card and 1 power card and add them to your hand. === Played out of turn in response to an attack or power card (except Swap) === Defence: You do not suffer the effect and the attackers or do not earn VP. Moreover, in case of attack countered attackers pawns are still repositioned. ce156f3f3e9446085508fb9ee60fba01e24f1c83 1692 1691 2015-12-04T03:14:23Z Senatorhung 4176 /* Played During Power Card Phase */ wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== === Power Cards Phase (optional) === You can use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. See section below for more details on each specific power card. === Movement Phase === You have to chose between: (a) drawing 2 movement cards; OR (b) use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : (a) moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise); OR (b) moving a meeple toward the card with the number indicated in the square. Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. === Resolving attacks and supplies === ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. === Redeployment === If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Card Details == (Card names may not match BGA exactly since Google translate used: http://www.ledernierpeuple.com/regles.php#but_du_jeu) === Played on your turn during Power Card phase === Strength: Win a token "2 VP" of the bank. Care: Win a token "1 VP" of the bank. Thief: Steal 1 VP to the player of your choice (if not token "1 VP", he must make change with the bank to give you that VP). Bandit: Steal a card at random from the hand of the player of your choice. Hex: The player must make your choice (if possible) 1 VP at the bank (if not token "1 VP", he must make change with the bank to make this VP). Black Magic: Randomly select from a card from an opponent's hand and discard the card without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Swap: Swap one of your pawns with the player of your choice. (Do not solve the possible action generated by this new configuration.) Chance: Draw 1 movement card and 1 power card and add them to your hand. === Played out of turn in response to an attack or power card (except Swap) === Defence: You do not suffer the effect and the attackers or do not earn VP. Moreover, in case of attack countered attackers pawns are still repositioned. 07726ea7bf639c97cd91f7727ebe9e00f8e5df3f 1693 1692 2015-12-04T03:17:28Z Senatorhung 4176 /* Played on your turn during Power Card phase */ wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== === Power Cards Phase (optional) === You can use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. See section below for more details on each specific power card. === Movement Phase === You have to chose between: (a) drawing 2 movement cards; OR (b) use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : (a) moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise); OR (b) moving a meeple toward the card with the number indicated in the square. Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. === Resolving attacks and supplies === ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. === Redeployment === If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Card Details == (Card names may not match BGA exactly since Google translate used: http://www.ledernierpeuple.com/regles.php#but_du_jeu) === Played on your turn during Power Card phase === Strength: Win 2 VPs from the bank. Care: Win 1 VP from the bank. Thief: Steal 1 VP from the player of your choice. Bandit: Steal a card at random from the hand of the player of your choice. Hex: The player of your choice returns 1 VP to the bank. Black Magic: Randomly select from a card from an opponent's hand and discard the card without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Swap: Swap one of your pawns with another pawn of the player of your choice. (Do not solve the possible action generated by this new configuration.) Chance: Draw 1 movement card and 1 power card and add them to your hand. === Played out of turn in response to an attack or power card (except Swap) === Defence: You do not suffer the effect and the attackers or do not earn VP. Moreover, in case of attack countered attackers pawns are still repositioned. c3ae38b8557b2cd00da329827ecf4b0834686e59 1694 1693 2015-12-04T03:17:51Z Senatorhung 4176 /* Played on your turn during Power Card phase */ wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== === Power Cards Phase (optional) === You can use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. See section below for more details on each specific power card. === Movement Phase === You have to chose between: (a) drawing 2 movement cards; OR (b) use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : (a) moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise); OR (b) moving a meeple toward the card with the number indicated in the square. Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. === Resolving attacks and supplies === ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. === Redeployment === If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Card Details == (Card names may not match BGA exactly since Google translate used: http://www.ledernierpeuple.com/regles.php#but_du_jeu) === Played on your turn during Power Card phase === Strength: Win 2 VPs from the bank. Care: Win 1 VP from the bank. Thief: Steal 1 VP from the player of your choice. Bandit: Steal a card at random from the hand of the player of your choice. Hex: The player of your choice returns 1 VP to the bank. Black Magic: Randomly select from a card from an opponent's hand and discard the card without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Swap: Swap one of your pawns with another pawn of the player of your choice. (Do not resolve the possible action generated by this new configuration.) Chance: Draw 1 movement card and 1 power card and add them to your hand. === Played out of turn in response to an attack or power card (except Swap) === Defence: You do not suffer the effect and the attackers or do not earn VP. Moreover, in case of attack countered attackers pawns are still repositioned. 02084bf3261be9b3ade14e73f945b2b01ea36f57 1695 1694 2015-12-04T03:19:42Z Senatorhung 4176 /* Played out of turn in response to an attack or power card (except Swap) */ wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== === Power Cards Phase (optional) === You can use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. See section below for more details on each specific power card. === Movement Phase === You have to chose between: (a) drawing 2 movement cards; OR (b) use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : (a) moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise); OR (b) moving a meeple toward the card with the number indicated in the square. Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. === Resolving attacks and supplies === ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. === Redeployment === If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Card Details == (Card names may not match BGA exactly since Google translate used: http://www.ledernierpeuple.com/regles.php#but_du_jeu) === Played on your turn during Power Card phase === Strength: Win 2 VPs from the bank. Care: Win 1 VP from the bank. Thief: Steal 1 VP from the player of your choice. Bandit: Steal a card at random from the hand of the player of your choice. Hex: The player of your choice returns 1 VP to the bank. Black Magic: Randomly select from a card from an opponent's hand and discard the card without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Swap: Swap one of your pawns with another pawn of the player of your choice. (Do not resolve the possible action generated by this new configuration.) Chance: Draw 1 movement card and 1 power card and add them to your hand. === Played out of turn in response to an attack or power card (except Swap) === Defence: You do not suffer the effect and the attackers do not earn VPs. Moreover, in case of attack countered attackers pawns are still repositioned. 5527a34d60cf8585b1dcb85f27cdc1347a568b17 1696 1695 2015-12-04T05:17:51Z Senatorhung 4176 /* Played on your turn during Power Card phase */ wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== === Power Cards Phase (optional) === You can use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. See section below for more details on each specific power card. === Movement Phase === You have to chose between: (a) drawing 2 movement cards; OR (b) use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : (a) moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise); OR (b) moving a meeple toward the card with the number indicated in the square. Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. === Resolving attacks and supplies === ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. === Redeployment === If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Card Details == (Card names may not match BGA exactly since Google translate used: http://www.ledernierpeuple.com/regles.php#but_du_jeu) === Played on your turn during Power Card phase === Strength: Win 2 VPs from the bank. Heal: Win 1 VP from the bank. Thief: Steal 1 VP from the player of your choice. Bandit: Steal a card at random from the hand of the player of your choice. Hex: The player of your choice returns 1 VP to the bank. Black Magic: Randomly select from a card from an opponent's hand and discard the card without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Swap: Swap one of your pawns with another pawn of the player of your choice. (Do not resolve the possible action generated by this new configuration.) Luck: Draw 1 movement card and 1 power card and add them to your hand. === Played out of turn in response to an attack or power card (except Swap) === Defence: You do not suffer the effect and the attackers do not earn VPs. Moreover, in case of attack countered attackers pawns are still repositioned. 614d8414be5cb8ab027c4b019b88b62e611a4aad 1697 1696 2015-12-04T13:01:23Z Senatorhung 4176 /* Movement Phase */ wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== === Power Cards Phase (optional) === You can use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. See section below for more details on each specific power card. === Movement Phase === You have to chose between: (a) drawing 2 movement cards; OR (b) use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : (a) moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise); OR (b) moving a meeple toward the card with the number indicated in the square. Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. === Resolving attacks and supplies === ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. === Redeployment === If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Card Details == (Card names may not match BGA exactly since Google translate used: http://www.ledernierpeuple.com/regles.php#but_du_jeu) === Played on your turn during Power Card phase === Strength: Win 2 VPs from the bank. Heal: Win 1 VP from the bank. Thief: Steal 1 VP from the player of your choice. Bandit: Steal a card at random from the hand of the player of your choice. Hex: The player of your choice returns 1 VP to the bank. Black Magic: Randomly select from a card from an opponent's hand and discard the card without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Swap: Swap one of your pawns with another pawn of the player of your choice. (Do not resolve the possible action generated by this new configuration.) Luck: Draw 1 movement card and 1 power card and add them to your hand. === Played out of turn in response to an attack or power card (except Swap) === Defence: You do not suffer the effect and the attackers do not earn VPs. Moreover, in case of attack countered attackers pawns are still repositioned. 1e85024e5f764f304fb6fcc707508a019164b46a 1701 1697 2015-12-07T02:57:14Z Eiraku 9066 /* Played on your turn during Power Card phase */ wikitext text/x-wiki In "Le Dernier Peuple" (The Last Folks), you personify a people. Each player has a "home" card which of his/her color. You play cards to move your 2 meeples around the cards's circle and gain points. == Goal == Reach 12 points. == A turn== === Power Cards Phase (optional) === You can use a power card (those cards are collected on pickaxes). Each card has a unique effect - read it by hovering the card in your hand with your mouse. See section below for more details on each specific power card. === Movement Phase === You have to chose between: (a) drawing 2 movement cards; OR (b) use 1 movement card then draw 1 movement card. A grey downward arrow allows you to move your meeple ; a black upward arrow allows you to move any opponent's meeple. Each arrow gives 2 possibilities : (a) moving a meeple by the number indicated in the circle (positive = clockwise ; negative = unclockwise); OR (b) moving a meeple toward the card with the number indicated in the square. Some movement cards have 2 small numbers next to the big circled number. The big number X is always the addition of the 2 small numbers Y and +/- 1 : X=Y+1 or X=Y-1. It means that, by using this card, you'll first move the meeple by Y cards, then see if an event (attack or supply) occurs. If yes, solve the event, and redeploy the involved meeples normally. If no event occurs, move the meeple once more. If your meeple ends up on a card with a pickaxe, you draw a power card (purple outline). You'll gain points by surrounding any "home" card with your 2 meeples or with 1 of your meeple and one opponent's meeple. === Resolving attacks and supplies === ''Supply'' : If a player surrounds his own "home" card with his 2 meeples, he gets 2 points. ''Noble Attack'' : If a player surrounds another player's "home" card with his 2 meeples, he wins 3 points, and the attacked ennemy loses 1 point. ''Sneaky attack'' : If a home card is surrounded by a meeple of the active player and another player's meeple, the active player gets 2 points, the other meeple's owner gets 1 point, and the attacked player loses 1 point. === Redeployment === If an attack or a supply has been made, then both meeples involved will be redeployed. The meeple of the active player gets redeployed first ; then the other meeple (of the same player, or of another player). A movement card is drawn, and the meeple is moved toward the card with the number indicated in the square. Same process for the second meeple. Basically, on BGA, this will mean the 2 meeples will be teleported randomly to some card on the board. == Power Card Details == (Card names may not match BGA exactly since Google translate used: http://www.ledernierpeuple.com/regles.php#but_du_jeu) === Played on your turn during Power Card phase === Strength: Win 2 VPs from the bank. Heal: Win 1 VP from the bank. Thief: Steal 1 VP from the player of your choice. Bandit: Steal a card at random from the hand of the player of your choice. Curse: The player of your choice returns 1 VP to the bank. Black Magic: Randomly select from a card from an opponent's hand and discard the card without applying the effect. Barter: Trade your hand of cards with the player of your choice. Speed: Play 2 consecutive rounds. Mace: The player of your choice must spend his next turn. Switch: Swap one of your pawns with another pawn of the player of your choice. (Do not resolve the possible action generated by this new configuration.) Luck: Draw 1 movement card and 1 power card and add them to your hand. === Played out of turn in response to an attack or power card (except Swap) === Defence: You do not suffer the effect and the attackers do not earn VPs. Moreover, in case of attack countered attackers pawns are still repositioned. 71ef57192de86177afc195accc274644e8d9e3bc Gamehelpsechsnimmt 0 174 1698 1579 2015-12-05T00:18:58Z Senatorhung 4176 /* Alternate Rules */ wikitext text/x-wiki == 6 nimmt! == The basic goal of the game is to avoid having to pick up cards, and try to force the other players to do so. Everyone starts with 66 points - you lose one for each "beef head" on a card you have to pick up. When one player has lost all of their points, the game will end at the end of the current round and the player with the most points left wins! === Playing the game === Everyone starts a round with 10 cards in their hand. Four cards are placed on the table to start four rows. Every player secretly chooses a card, and then all of the cards are revealed at the same time. When the cards are revealed, they are placed on the ends of rows, from lowest value played to highest, following two rules: 1. cards are always placed in ascending order. 2. cards are always placed next to the card on the board with the smallest difference between them. As play progresses, the rows will fill up with cards - at five cards, a row is full. If someone's card would go onto a full row, that player has to pick up all of the cards in that row, and they lose as many points as there are "beef heads" on the cards (different cards are worth different amounts - more on that in a moment). The card that the person played becomes the starting point of a new row. If someone plays a card that is lower than the numbers at the end of all of the rows, then that player must take a row of their choice, and start a new row in its place with their card. '''Bull heads''' Each card has a number of bull heads on it - this indicates how many points it is worth when it is picked up. Cards which end in the number "5" (ex. 5, 15, 25) are worth 2 points. Cards which end in the number "0" (10, 20, 30) are worth 3 points. Cards which have double numbers (11, 22, 33) are worth 5 points. The "55" card has both a "5" and double numbers, and is worth 7 points. All other cards are worth 1 point. '''End of a round''' Once a round ends, if no one has lost all of their points, then a new round begins. If someone is out of points, then the game is over and whoever still has the most points is the winner. === Alternate Rules === '''Tactics:''' This ruleset changes the number of cards in play based on how many people are playing - other than that the rules are the same. The number of cards is equal to the number of players plus 4, so every card that could be played will find its way onto the table at some point. This changes strategy some and makes paying attention to which cards are have yet to be played important. '''Logic:''' The same as Tactics, except that at the start of the round all of the cards are placed on the table face up, and players take turns choosing cards one at a time to build their hands before the round proper starts. '''Professional:''' Cards are played to the left OR the right, depending on which is closest in numerical value. fb425e21efe236a1acc975632a4d3055f907d58c 1699 1698 2015-12-05T01:12:13Z Senatorhung 4176 /* Alternate Rules */ wikitext text/x-wiki == 6 nimmt! == The basic goal of the game is to avoid having to pick up cards, and try to force the other players to do so. Everyone starts with 66 points - you lose one for each "beef head" on a card you have to pick up. When one player has lost all of their points, the game will end at the end of the current round and the player with the most points left wins! === Playing the game === Everyone starts a round with 10 cards in their hand. Four cards are placed on the table to start four rows. Every player secretly chooses a card, and then all of the cards are revealed at the same time. When the cards are revealed, they are placed on the ends of rows, from lowest value played to highest, following two rules: 1. cards are always placed in ascending order. 2. cards are always placed next to the card on the board with the smallest difference between them. As play progresses, the rows will fill up with cards - at five cards, a row is full. If someone's card would go onto a full row, that player has to pick up all of the cards in that row, and they lose as many points as there are "beef heads" on the cards (different cards are worth different amounts - more on that in a moment). The card that the person played becomes the starting point of a new row. If someone plays a card that is lower than the numbers at the end of all of the rows, then that player must take a row of their choice, and start a new row in its place with their card. '''Bull heads''' Each card has a number of bull heads on it - this indicates how many points it is worth when it is picked up. Cards which end in the number "5" (ex. 5, 15, 25) are worth 2 points. Cards which end in the number "0" (10, 20, 30) are worth 3 points. Cards which have double numbers (11, 22, 33) are worth 5 points. The "55" card has both a "5" and double numbers, and is worth 7 points. All other cards are worth 1 point. '''End of a round''' Once a round ends, if no one has lost all of their points, then a new round begins. If someone is out of points, then the game is over and whoever still has the most points is the winner. === Alternate Rules === '''Tactics:''' This ruleset changes the number of cards in play based on how many people are playing - other than that the rules are the same. The number of cards is equal to the number of players plus 4, so every card that could be played will find its way onto the table at some point. This changes strategy some and makes paying attention to which cards are have yet to be played important. '''Logic:''' The same as Tactics, except that at the start of the round all of the cards are placed on the table face up, and players take turns choosing cards one at a time to build their hands before the round proper starts. '''Professional:''' Cards are played to the left OR the right, depending on which is closest in numerical value. The card that the person played becomes the starting point of a new row. 1d2c3e37b79a76d0a8fc88fb882c8f361bc83411 Kaozeal:Gamehelpsaboteur 1 205 1700 2015-12-05T02:01:30Z Zestynachos 9857 Created page with "The link for the Saboteur rules appears to be broken, where can those links be changed? I found a rule book which adds both rule sets together: [http://www.wardman.org/wp-cont..." wikitext text/x-wiki The link for the Saboteur rules appears to be broken, where can those links be changed? I found a rule book which adds both rule sets together: [http://www.wardman.org/wp-content/uploads/2012/05/saboteur.pdf] aa5b18485c6225aeda9a10faf9c97b387bc97362 Gamehelptashkalar 0 177 1702 1649 2015-12-07T09:58:36Z Quinarbre 4507 wikitext text/x-wiki == Game forms == On Board Game Arena, Tash-Kalar may be played by 2 to 4 players), and in 2 distinct forms : - '''The High Form''': Players score points for tasks and for legendary pieces currently on the board, only available for 2 players. - '''Deathmatch''': No tasks. Players score points for destroying enemy pieces, for summoning legendary beings, and when their opponents invoke a flare. Deathmatch can be played by 2 to 4 players. The actual board game also features team play in both forms. == Setup == Each player draws 6 cards : 3 beings from his or her own deck, 2 legends, and 1 flare. In '''High Form''', 3 tasks are revealed that may be claimed, along with a fourth "next task". In '''Deathmatch''', the player who plays second puts one common piece of each color on the game board, on marked squares. == Game play == Players take turns in clockwise order, beginning with the starting player. Each turn, you have 2 actions. Exception: The starting player has only 1 action on his or her first turn. Possible actions: - '''Place 1 common piece''' of your color on any empty square. If you have none left to place, you begin this action by picking up 1 of your common or heroic pieces, then place it as a common piece. - '''Summon a being'''. (See below.) - '''Discard 1 being''' that you drew from your deck. If you do, you may also return one or more of your other cards to the bottoms of their decks. Actions can be done in any order. You can do more than one “place” or “summon” action per turn (but no more than one “discard” action). You have to use all your actions. You can invoke a flare (see below) before or after any action. Invoking a flare does not cost you an action. Finish your turn by drawing cards so that you end up with 3 beings from your deck, 2 legends, and 1 flare. If you draw the last card in your deck, you may end up with fewer than 3. '''High Form''': At the end of the turn, you may claim exactly 1 of the current tasks, if you meet its criteria. '''Deathmatch''': At the end of your turn, score points for destroyed enemy pieces: 2 points for legendary, 1 point for heroic, 1 point for each pair of common pieces. In Deathmatch Melee (3-4 players) you keep a separate count of colored points against each of your opponents. Your final score is the '''lowest''' of all your colored scores. You get no points for destroying your own pieces. You get no points for an un- paired common piece, but you can pair two common pieces in different colors. Also score 1 point (in the color of your choice) each time you summon a legend. (Upgrading a heroic piece does not count as “summoning a legend”.) == Summoning a being == To summon a being, use 1 action and do the following: - '''Play the card''' from your hand and choose a square on the board where your pieces match the pattern on the card. The pattern can be rotated (by 90, 180, or 270 degrees). Mirror images and flips also count as a match. The pieces used to summon the being can be the same rank as those depicted in the pattern or higher rank. Empty squares are not important to the pattern. - '''Place a piece of the indicated rank''' (upper left corner of the card) on the square indicated by the white-framed square in the pattern. This square may be empty, unless the pattern says it must be occupied by one of your pieces. If the square is occupied by a piece of the same rank or lower, destroy that piece when you put the new piece on the square. If the square is occupied by a piece of higher rank, you cannot summon the being. If all your pieces of that type are already on the board, you may still be able to summon the being by picking up a piece that is not required for the pattern and use it as the new piece. - Once the new piece is on the board, '''resolve the effect''' printed on the card. - After resolving the effect, discard the card. == Invoking a flare == You can invoke a flare on your turn before or after any action. To invoke a flare, you must meet at least one of the criteria: - You meet the upper criterion if one of your opponents has '''that many more upgraded pieces''' (heroic and legendary) on the board than you. - You meet the lower criterion if one of your opponents has '''that many more pieces (total)''' on the board than you. If you meet the upper criterion, you resolve the upper effect. If you meet the lower criterion, you resolve the lower effect. If you meet both, you resolve the upper effect first, then the lower. If you meet the criteria against several opponents, you choose against whom you compare. Once the card has been resolved, discard it. == Resolving effects of beings and flares == No other action can be taken and no flare can be invoked until the entire effect of the card is resolved. Some parts of an effect may be optional: - May indicates that a certain part of an effect is optional. - Up to always includes 0. Any parts that are not specified as optional are mandatory. If an effect cannot be performed fully, do the parts that can be done. When a card uses its own name, it is referring to the piece on the board that represents the summoned being. '''Keywords''': - Upgraded piece: a heroic or legendary piece. - Non-legendary piece: a common or heroic piece. - Piece: If a piece is not specified as belonging to you or an opponent, then the effect includes any player's piece. - Marked space: a colored space in the pattern. If the text does not refer to marked spaces, the colored spaces in the pattern are just illustrational. - Adjacent square: one of eight squares sharing an edge (orthogonally adjacent) or a corner (diagonally adjacent) with a given square. If the given square is not specified, assume it is the square currently occupied by the newly summoned piece. - Distance: the shortest number of moves required to get from one square to another. For example, adjacent squares are at distance 1. - Move: A move is always onto an adjacent square. A move onto an occupied square destroys the piece that was there. - Standard move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Combat move: This type of move can be only onto an empty square or a square occupied by a piece of equal or lower rank. - Standard leap and combat leap: A leap is the same as a move, except the square doesn’t have to be adjacent. If not specified, a leap can be onto any square on the board. - Place: Like the “place” action. However, if there is no piece of the specified color and rank available, the piece cannot be placed. - Upgrade: Legendary pieces cannot be upgraded. To upgrade a common piece, flip it over. To upgrade a heroic piece, remove it and replace it with a legendary piece. If none is available, the heroic piece cannot be upgraded. - Downgrade: Common pieces cannot be downgraded. To downgrade a heroic piece, flip it over. To downgrade a legendary piece, replace it with a heroic piece. If none is available, the legendary piece cannot be downgraded. - Destroy: To destroy a piece, remove it from the board. - Convert: To convert an enemy piece, replace it with one of your pieces of the same rank (unless a different rank is specified). When keeping track of '''how many enemy pieces you destroyed''', count pieces you destroyed during summoning, pieces you destroyed with moves and leaps, pieces you destroyed with a “destroy” effect, and pieces you converted. Neither upgrading nor downgrading ever counts as destroying a piece. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. ---- These rules are extracted from CGE's full rules for Tash-Kalar. a678015270a6b41e06858341b0eda4375057fcdb Game meta-information: gameinfos.inc.php 0 130 1703 1583 2015-12-11T09:43:33Z Sourisdudesert 1 wikitext text/x-wiki From this file, you can edit the various meta-information of your game. Once you modified the file, don't forget to click on "Reload game informations" from the Control Panel in order in can be taken into account. Most information provided in this file are self-explainable. Some information, though: * You are not allowed to set the "'''is_beta'''" to 0 before the game has been released on BGA and stabilized. * "'''fast/medium/slow_additional_time'''": please set high values here: after the game has been released, we will lower these value to match the real game duration. * "'''players'''": ** during the first step of development of a game, you'd better allow the "1 player" configuration: much easy to start/stop a game this way. ** if you change the minimum number of players from for example 1 to 2, make sure the new tables you create are not restricted from 1 to 1 player otherwise when you create a new table and this account setting is used, there will be a conflict with the new minimum number of players allowed. * '''suggest_player_number''' / '''not_recommend_player_number''': don't specify anything here if there is no configuration that is REALLY better/worst than another one. You can check player's poll on BoardGameGeek game page if you have any doubt. == Tags == Any number of '''Tags''' can be attribute to your game. Tags are useful to place your game in the correct place and to give a good quick overview of what the game is about to players. Main game category (you MUST specify one tag AND ONLY ONE from this category): * 1: Abstract game * 2: Casual games * 3: For regular players * 4: For core gamers Other tags (you can specify any numbers of tags): * 10: Short game (<10 minutes) * 11: Medium length game (10 minutes to 30 minutes) * 12: Long game (>30mn) * 20: Awarded game (Win a prestigious award) (the game must have been at the '''first''' place of one the [http://boardgamegeek.com/wiki/page/Gaming_Industry_Awards# following major awards list]). * 22: Prototype (This game has not been published yet) * 23: Classic (This game is a classic from Public Domain) * 30: 2 players (2p game / best with 2 players) * 100: Fantasy theme * 101: Science Fiction them * 102: Historical theme * 103: Adventure * 104: Exploration * 105: Conquest * 106: Building * 200: Card game (Cards plays a central role in this game) * 201: Dice * 202: Solo game * 203: Worker placement * 204: Hand management * 205: Bluff * 206: Tile placement * 207: Combinations * 208: Majority * 209: Race * 210: Collection c35af69aa4fb61f473823006be2ba36446d4b260 Kaozeal:Contact us 1 206 1704 2015-12-21T07:08:43Z Karentw 10892 Created page with " Dear friends, i want to open board game restaurant, and plan to buy 300-500 kinds of games. any suggestine where i can buy and have good price?" wikitext text/x-wiki Dear friends, i want to open board game restaurant, and plan to buy 300-500 kinds of games. any suggestine where i can buy and have good price? 1b307670e39f466122248894f5582913e5a3b65c Gamehelpdarkagent 0 207 1705 2015-12-23T14:41:29Z Philcollins 10686 Created page with " == Pitch of DARK AGENT board game : == You are the head of an international agency and you will have to send your spies in mission, neutralize sentinels or opponent agents a..." wikitext text/x-wiki == Pitch of DARK AGENT board game : == You are the head of an international agency and you will have to send your spies in mission, neutralize sentinels or opponent agents and win aims. Thanks to your satellites that will locate the various actors in the theatre of operations. == Game tactics : == This game is rich of tactical and strategic possibilities. Players can take the game in hand before the first three plays. It has many strenghs : - Game duration could be calibrated (2 players / aim, the game lasts less than 10 minutes). - Play turns are smooth, even with 6 players (calibrated in duration with the number of aims to win in order to make a short/long play) - The single player mode is a real challenge and allows to understand the mechanisms. - There are many strategies and many ways to win. == Tutorials == Youtube tutorials are available : search spacereindeers, are go to [http://www.spacereindeers.com/darkagent link DarkAgent] 93e8ca95c90ef81a6b28253260f16e294b2b74ac 1706 1705 2015-12-23T14:46:24Z Philcollins 10686 /* Tutorials */ wikitext text/x-wiki == Pitch of DARK AGENT board game : == You are the head of an international agency and you will have to send your spies in mission, neutralize sentinels or opponent agents and win aims. Thanks to your satellites that will locate the various actors in the theatre of operations. == Game tactics : == This game is rich of tactical and strategic possibilities. Players can take the game in hand before the first three plays. It has many strenghs : - Game duration could be calibrated (2 players / aim, the game lasts less than 10 minutes). - Play turns are smooth, even with 6 players (calibrated in duration with the number of aims to win in order to make a short/long play) - The single player mode is a real challenge and allows to understand the mechanisms. - There are many strategies and many ways to win. == Tutorials == Youtube tutorials are available : search spacereindeers, are go to [http://www.spacereindeers.com/dark-agent link DarkAgent] 4a92abec5cea68e5fef3cd095600a0aa88e38f79 1707 1706 2015-12-23T19:48:49Z Philcollins 10686 /* Tutorials */ wikitext text/x-wiki == Pitch of DARK AGENT board game : == You are the head of an international agency and you will have to send your spies in mission, neutralize sentinels or opponent agents and win aims. Thanks to your satellites that will locate the various actors in the theatre of operations. == Game tactics : == This game is rich of tactical and strategic possibilities. Players can take the game in hand before the first three plays. It has many strenghs : - Game duration could be calibrated (2 players / aim, the game lasts less than 10 minutes). - Play turns are smooth, even with 6 players (calibrated in duration with the number of aims to win in order to make a short/long play) - The single player mode is a real challenge and allows to understand the mechanisms. - There are many strategies and many ways to win. == Tutorials == Youtube tutorials are available : search spacereindeers, or go to [http://www.spacereindeers.com/dark-agent link DarkAgent] e34346c46585ecd580b706a4e0ed64bdb98585bb 1726 1707 2015-12-29T21:35:09Z Philcollins 10686 /* Pitch of DARK AGENT board game : */ wikitext text/x-wiki == Pitch of DARK AGENT board game : == You are the head of an international agency and you will have to send your spies in mission, neutralize sentinels or opponent agents and win aims. Thanks to your satellites that will locate the various actors in the theatre of operations. == Equipment cards effects == ---- Adrenaline : Boost an agent with a bonus equal to his basic level -------- Binoculars : add two markers 'attempts' on an aim, then it's easier to attack it ---- Bulletproof jacket : Gives you invulnerability till a missed attack. Must be used before attack with at least a spy selected. Can be used for Defense, after dice result in case one of your spy is attacked (then Discarded). ---- Explosives : Allow to attack protected aims (with sentinel or enemy spy around) ---- Jet-pack : You can exchange place of one of your spy with the place of an opponent spy or a sentinel. ---- Rifle : Add +2 to all your attack, and allow you to attack one sentinel (spotted or not), wherever on the TDO (theater of operations). Allow you to re-attack a sentinel by this way. ---- Rocket launcher : Use before attack, allow to change a dice on each attack (to get a six for example). One spy must be selected before using this equipment ---- Rubber dinghy (boat) : Use this equipment to send a spy on the TDO, you must have an free square available on the TDO to do this (where the spy will land) ---- Sat-laptop : This Laptop will allow you to use a satellite from other players to spot a new square on the TDO. Cannot be used for neutral sat, except in 1-player game. Cannot be used twice the same row in the same turn. ---- == Game tactics : == This game is rich of tactical and strategic possibilities. Players can take the game in hand before the first three plays. It has many strenghs : - Game duration could be calibrated (2 players / aim, the game lasts less than 10 minutes). - Play turns are smooth, even with 6 players (calibrated in duration with the number of aims to win in order to make a short/long play) - The single player mode is a real challenge and allows to understand the mechanisms. - There are many strategies and many ways to win. == Tutorials == Youtube tutorials are available : search spacereindeers, or go to [http://www.spacereindeers.com/dark-agent link DarkAgent] 810155ac0c43ca88f5b79a90e4cf3cdbb20d67e1 1727 1726 2015-12-29T21:35:29Z Philcollins 10686 /* Equipment cards effects */ wikitext text/x-wiki == Pitch of DARK AGENT board game : == You are the head of an international agency and you will have to send your spies in mission, neutralize sentinels or opponent agents and win aims. Thanks to your satellites that will locate the various actors in the theatre of operations. == Equipment cards effects == Adrenaline : Boost an agent with a bonus equal to his basic level -------- Binoculars : add two markers 'attempts' on an aim, then it's easier to attack it ---- Bulletproof jacket : Gives you invulnerability till a missed attack. Must be used before attack with at least a spy selected. Can be used for Defense, after dice result in case one of your spy is attacked (then Discarded). ---- Explosives : Allow to attack protected aims (with sentinel or enemy spy around) ---- Jet-pack : You can exchange place of one of your spy with the place of an opponent spy or a sentinel. ---- Rifle : Add +2 to all your attack, and allow you to attack one sentinel (spotted or not), wherever on the TDO (theater of operations). Allow you to re-attack a sentinel by this way. ---- Rocket launcher : Use before attack, allow to change a dice on each attack (to get a six for example). One spy must be selected before using this equipment ---- Rubber dinghy (boat) : Use this equipment to send a spy on the TDO, you must have an free square available on the TDO to do this (where the spy will land) ---- Sat-laptop : This Laptop will allow you to use a satellite from other players to spot a new square on the TDO. Cannot be used for neutral sat, except in 1-player game. Cannot be used twice the same row in the same turn. == Game tactics : == This game is rich of tactical and strategic possibilities. Players can take the game in hand before the first three plays. It has many strenghs : - Game duration could be calibrated (2 players / aim, the game lasts less than 10 minutes). - Play turns are smooth, even with 6 players (calibrated in duration with the number of aims to win in order to make a short/long play) - The single player mode is a real challenge and allows to understand the mechanisms. - There are many strategies and many ways to win. == Tutorials == Youtube tutorials are available : search spacereindeers, or go to [http://www.spacereindeers.com/dark-agent link DarkAgent] 49c77c697ae2b0442ec3408d85d47c7398713248 1728 1727 2015-12-29T21:36:02Z Philcollins 10686 /* Pitch of DARK AGENT board game : */ wikitext text/x-wiki == Pitch of DARK AGENT board game : == You are the head of an international agency and you will have to send your spies in mission, neutralize sentinels or opponent agents and win aims. Thanks to your satellites that will locate the various actors in the theatre of operations. == Equipment cards effects == Adrenaline : Boost an agent with a bonus equal to his basic level -------- Binoculars : add two markers 'attempts' on an aim, then it's easier to attack it ---- Bulletproof jacket : Gives you invulnerability till a missed attack. Must be used before attack with at least a spy selected. Can be used for Defense, after dice result in case one of your spy is attacked (then Discarded). ---- Explosives : Allow to attack protected aims (with sentinel or enemy spy around) ---- Jet-pack : You can exchange place of one of your spy with the place of an opponent spy or a sentinel. ---- Rifle : Add +2 to all your attack, and allow you to attack one sentinel (spotted or not), wherever on the TDO (theater of operations). Allow you to re-attack a sentinel by this way. ---- Rocket launcher : Use before attack, allow to change a dice on each attack (to get a six for example). One spy must be selected before using this equipment ---- Rubber dinghy (boat) : Use this equipment to send a spy on the TDO, you must have an free square available on the TDO to do this (where the spy will land) ---- Sat-laptop : This Laptop will allow you to use a satellite from other players to spot a new square on the TDO. Cannot be used for neutral sat, except in 1-player game. Cannot be used twice the same row in the same turn. == Game tactics : == This game is rich of tactical and strategic possibilities. Players can take the game in hand before the first three plays. It has many strenghs : - Game duration could be calibrated (2 players / aim, the game lasts less than 10 minutes). - Play turns are smooth, even with 6 players (calibrated in duration with the number of aims to win in order to make a short/long play) - The single player mode is a real challenge and allows to understand the mechanisms. - There are many strategies and many ways to win. == Tutorials == Youtube tutorials are available : search spacereindeers, or go to [http://www.spacereindeers.com/dark-agent link DarkAgent] 09ea241753f3c8f216692ac7b19849b7db9bed10 1729 1728 2015-12-29T22:09:51Z Philcollins 10686 /* Equipment cards effects */ wikitext text/x-wiki == Pitch of DARK AGENT board game : == You are the head of an international agency and you will have to send your spies in mission, neutralize sentinels or opponent agents and win aims. Thanks to your satellites that will locate the various actors in the theatre of operations. == Equipment cards effects == Adrenaline : Boost an agent with a bonus equal to his basic level -------- Binoculars : add two markers 'attempts' on an aim, then it's easier to attack it ---- Bulletproof jacket : Gives you invulnerability till a missed attack. Must be used before attack with at least a spy selected. Can be used for Defense, after dice result in case one of your spy is attacked (then Discarded). ---- Explosives : Allow to attack protected aims (with sentinel or enemy spy around) ---- Jet-pack : You can exchange place of one of your spy with the place of an opponent spy or a sentinel. ---- Rifle : Add +2 to all your attack, and allow you to attack one sentinel (spotted or not), wherever on the TDO (theater of operations). Allow you to re-attack a sentinel by this way. ---- Rocket launcher : Use before attack, allow to change a dice on each attack (to get a six for example). One spy must be selected before using this equipment ---- Rubber dinghy (boat) : Use this equipment to send a spy on the TDO, you must have an free square available on the TDO to do this (where the spy will land) ---- Sat-laptop : This Laptop will allow you to use a satellite from other players to spot a new square on the TDO. Cannot be used for neutral sat, except in 1-player game. Cannot be used twice the same row in the same turn. == Permanent power of Aims == Prisoner : Once by turn, exchange place of one of your spy with an enemy (dark agent, opponent spy or sentinel) ---- Scientist : All of your spies get invulnerability ---- Nuclear deterrence : All your attacks get +2 bonus ---- Control Center : All your satellites are supers-satellites ---- Briefcase : One more vote FOR if you vote FOR the peace == Game tactics : == This game is rich of tactical and strategic possibilities. Players can take the game in hand before the first three plays. It has many strenghs : - Game duration could be calibrated (2 players / aim, the game lasts less than 10 minutes). - Play turns are smooth, even with 6 players (calibrated in duration with the number of aims to win in order to make a short/long play) - The single player mode is a real challenge and allows to understand the mechanisms. - There are many strategies and many ways to win. == Tutorials == Youtube tutorials are available : search spacereindeers, or go to [http://www.spacereindeers.com/dark-agent link DarkAgent] 77550de764b6bdf8104bbeeceabe33463302643c 1730 1729 2015-12-29T22:10:08Z Philcollins 10686 /* Permanent power of Aims */ wikitext text/x-wiki == Pitch of DARK AGENT board game : == You are the head of an international agency and you will have to send your spies in mission, neutralize sentinels or opponent agents and win aims. Thanks to your satellites that will locate the various actors in the theatre of operations. == Equipment cards effects == Adrenaline : Boost an agent with a bonus equal to his basic level -------- Binoculars : add two markers 'attempts' on an aim, then it's easier to attack it ---- Bulletproof jacket : Gives you invulnerability till a missed attack. Must be used before attack with at least a spy selected. Can be used for Defense, after dice result in case one of your spy is attacked (then Discarded). ---- Explosives : Allow to attack protected aims (with sentinel or enemy spy around) ---- Jet-pack : You can exchange place of one of your spy with the place of an opponent spy or a sentinel. ---- Rifle : Add +2 to all your attack, and allow you to attack one sentinel (spotted or not), wherever on the TDO (theater of operations). Allow you to re-attack a sentinel by this way. ---- Rocket launcher : Use before attack, allow to change a dice on each attack (to get a six for example). One spy must be selected before using this equipment ---- Rubber dinghy (boat) : Use this equipment to send a spy on the TDO, you must have an free square available on the TDO to do this (where the spy will land) ---- Sat-laptop : This Laptop will allow you to use a satellite from other players to spot a new square on the TDO. Cannot be used for neutral sat, except in 1-player game. Cannot be used twice the same row in the same turn. == Permanent power of Aims == Prisoner : Once by turn, exchange place of one of your spy with an enemy (dark agent, opponent spy or sentinel) ---- Scientist : All of your spies get invulnerability ---- Nuclear deterrence : All your attacks get +2 bonus ---- Control Center : All your satellites are supers-satellites ---- Briefcase : One more vote FOR if you vote FOR the peace == Game tactics : == This game is rich of tactical and strategic possibilities. Players can take the game in hand before the first three plays. It has many strenghs : - Game duration could be calibrated (2 players / aim, the game lasts less than 10 minutes). - Play turns are smooth, even with 6 players (calibrated in duration with the number of aims to win in order to make a short/long play) - The single player mode is a real challenge and allows to understand the mechanisms. - There are many strategies and many ways to win. == Tutorials == Youtube tutorials are available : search spacereindeers, or go to [http://www.spacereindeers.com/dark-agent link DarkAgent] 7c5d4a52ed6aed5acf53ab00dc381a6d8c708aa5 1731 1730 2015-12-29T22:10:31Z Philcollins 10686 /* Equipment cards effects */ wikitext text/x-wiki == Pitch of DARK AGENT board game : == You are the head of an international agency and you will have to send your spies in mission, neutralize sentinels or opponent agents and win aims. Thanks to your satellites that will locate the various actors in the theatre of operations. == Equipment cards effects == Adrenaline : Boost an agent with a bonus equal to his basic level -------- Binoculars : add two markers 'attempts' on an aim, then it's easier to attack it ---- Bulletproof jacket : Gives you invulnerability till a missed attack. Must be used before attack with at least a spy selected. Can be used for Defense, after dice result in case one of your spy is attacked (then Discarded). ---- Explosives : Allow to attack protected aims (with sentinel or enemy spy around) ---- Jet-pack : You can exchange place of one of your spy with the place of an opponent spy or a sentinel. ---- Rifle : Add +2 to all your attack, and allow you to attack one sentinel (spotted or not), wherever on the TDO (theater of operations). Allow you to re-attack a sentinel by this way. ---- Rocket launcher : Use before attack, allow to change a dice on each attack (to get a six for example). One spy must be selected before using this equipment ---- Rubber dinghy (boat) : Use this equipment to send a spy on the TDO, you must have an free square available on the TDO to do this (where the spy will land) ---- Sat-laptop : This Laptop will allow you to use a satellite from other players to spot a new square on the TDO. Cannot be used for neutral sat, except in 1-player game. Cannot be used twice the same row in the same turn. == Permanent power of Aims == Prisoner : Once by turn, exchange place of one of your spy with an enemy (dark agent, opponent spy or sentinel) ---- Scientist : All of your spies get invulnerability ---- Nuclear deterrence : All your attacks get +2 bonus ---- Control Center : All your satellites are supers-satellites ---- Briefcase : One more vote FOR if you vote FOR the peace == Game tactics : == This game is rich of tactical and strategic possibilities. Players can take the game in hand before the first three plays. It has many strenghs : - Game duration could be calibrated (2 players / aim, the game lasts less than 10 minutes). - Play turns are smooth, even with 6 players (calibrated in duration with the number of aims to win in order to make a short/long play) - The single player mode is a real challenge and allows to understand the mechanisms. - There are many strategies and many ways to win. == Tutorials == Youtube tutorials are available : search spacereindeers, or go to [http://www.spacereindeers.com/dark-agent link DarkAgent] 681aa4fef24a827346ba185d67778adf4c3e33c5 Gamehelpbattleoflits 0 208 1708 2015-12-24T02:14:07Z Chaotic iak 3338 Created page with "Battle of LITS is an abstract board game for 2 players. Players take turn placing tetrominoes (blocks of 4 squares, like Tetris pieces) onto the grid, following the rules of t..." wikitext text/x-wiki Battle of LITS is an abstract board game for 2 players. Players take turn placing tetrominoes (blocks of 4 squares, like Tetris pieces) onto the grid, following the rules of the puzzle LITS, as they secure their own symbols and cover the opponent's symbols. When there is no more piece that can be played, the player with more symbols still uncovered wins. == Start of the game == The board is 10x10 by size. Players can agree to play a predetermined pattern of symbols, or choose a random selection; in either case, each player will have 30 squares marked with their symbol. One player plays with X, the other O. == Player's turn == In a player's turn, a player must play a piece. Pieces occupy four squares, and are of four different shapes: L, I, T, and S. A piece must be played to follow the following rules: * A piece must be played adjacent to a previously played piece (except, obviously, for the first piece played). * There can be no 2x2 square completely covered by pieces. * Two identical pieces may not be adjacent. Otherwise, a player is free to play any piece in any position their wish, including rotating and reflecting the piece. The piece may cover any number of symbols of either player; the symbols only affect the scoring, not the legal plays. There are only five pieces of each shape, and this pool of pieces is shared between both players. If a shape is exhausted, neither player can play more of that shape. After playing a piece, the turn passes to the opponent. == The first turn and the pie rule == After the first turn, the second player has the option of switching sides. This switches the symbols of the players, and the second player takes the played move as theirs instead and letting the opponent to go again, effectively making the second player to be the first player. This "pie rule" option only exists in the first turn. == End of the game == If either player can no longer play any piece, the game ends. The player with more of their symbols that are still uncovered wins the game. In case of a tie, the player that played the last piece wins. ea6f7a0b9ac019ad55defe8947b23d4cb3a01aa6 1724 1708 2015-12-28T19:02:36Z Chaotic iak 3338 wikitext text/x-wiki Battle of LITS is an abstract board game for 2 players. Players take turn placing tetrominoes (blocks of 4 squares, like Tetris pieces) onto the grid, following the rules of the puzzle LITS, as they secure their own symbols and cover the opponent's symbols. When there is no more piece that can be played, the player with more symbols still uncovered wins. == Start of the game == The board is 10x10 by size. Players can agree to play a predetermined pattern of symbols, or choose a random selection. With random selection, each player will have 30 symbols. (All but one of the patterns also have 30 symbols per player.) One player plays with X, the other O; the X player starts. == Player's turn == In a player's turn, a player must play a piece. Pieces occupy four squares, and are of four different shapes: L, I, T, and S. A piece must be played to follow the following rules: * A piece must be played adjacent to a previously played piece (except, obviously, for the first piece played). * There can be no 2x2 square completely covered by pieces. * Two identical pieces may not be adjacent. Otherwise, a player is free to play any piece in any position their wish, including rotating and reflecting the piece. The piece may cover any number of symbols of either player; the symbols only affect the scoring, not the legal plays. There are only five pieces of each shape, and this pool of pieces is shared between both players. If a shape is exhausted, neither player can play more of that shape. After playing a piece, the turn passes to the opponent. == The first turn and the pie rule == After the first turn, the second player has the option of switching sides. This switches the symbols of the players, and the second player takes the played move as theirs instead and letting the opponent to go again, effectively making the second player to be the first player. This "pie rule" option only exists in the first turn. == End of the game == If either player can no longer play any piece, the game ends. The player with more of their symbols that are still uncovered wins the game. In case of a tie, the player that played the last piece wins. 9df74dd66a7c4233084bbc9be1663c6e1fd42663 Studio 0 49 1709 956 2015-12-26T11:41:46Z Sourisdudesert 1 /* Game interface */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the latest information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) BGA Studio website: http://en.studio.boardgamearena.com (original announcement on BGA forum: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973) == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum''']. == BGA Studio documentation == === BGA Studio Framework reference === This part of the documentation focuses on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] * [[Your game mobile version]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game meta-information: gameinfos.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a &lt;div&gt; element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. * [[Tools and tips of BGA Studio]] * [[Practical debugging]] * [[Studio logs]] * [[Studio FAQ]] == BGA Developer team organization == * [[Steps to create a BGA game]] * [[Post-release phase]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] 68dbfd738b3b61488f584afd7ee9a49ab6d47500 Your game mobile version 0 209 1710 2015-12-26T11:45:39Z Sourisdudesert 1 Created page with " Board Game Arena is now adaptated for Mobiles and Tablets too. This is very easy to have a mobile version of the game you developed with BGA Studio. In fact, your game is pr..." wikitext text/x-wiki Board Game Arena is now adaptated for Mobiles and Tablets too. This is very easy to have a mobile version of the game you developed with BGA Studio. In fact, your game is probably already 100% playable on mobile. However, to provide your players the best experience, you should follow the 2 advices below. == Touchscreen compatibility == When your game is running on a touchscreen device, the global CSS class "touch-device" is added to the root HTML element (and "notouch-device" is added in the contrary). c7cfbd417315c2f66662ba9ce72da11147a8adbd 1711 1710 2015-12-26T11:49:49Z Sourisdudesert 1 wikitext text/x-wiki Board Game Arena is now adaptated for Mobiles and Tablets too. This is very easy to have a mobile version of the game you developed with BGA Studio. In fact, your game is probably already 100% playable on mobile. However, to provide your players the best experience, you should follow the 2 advices below. == Touchscreen compatibility == Most of your game should work with touchscreen device. Note : When your game is running on a touchscreen device, the global CSS class "touch-device" is added to the root HTML element (and "notouch-device" is added in the contrary). What may not work : * ":hover" CSS switch. Because there is no mouse, ":hover" won't be triggered. This is not an issue unless it is needed to play the game. In addition, some touch device considers that a short touch must trigger a ":hover" (and should apply corresponding CSS), which can block an interaction in your game. We advise you to explicitely disable ":hover" effects when your game is running on a touchscreen device. 96c67ccc5897e60331a69f1f56991f504174952d 1712 1711 2015-12-26T11:53:54Z Sourisdudesert 1 wikitext text/x-wiki Board Game Arena is now adaptated for Mobiles and Tablets too. This is very easy to have a mobile version of the game you developed with BGA Studio. In fact, your game is probably already 100% playable on mobile. However, to provide your players the best experience, you should follow the 2 advices below. == Touchscreen compatibility == Most of your game should work with touchscreen device. Note : When your game is running on a touchscreen device, the global CSS class "touch-device" is added to the root HTML element (and "notouch-device" is added in the contrary). What may not work : * ":hover" CSS switch. Because there is no mouse, ":hover" won't be triggered. This is not an issue unless it is needed to play the game. In addition, some touch device considers that a short touch must trigger a ":hover" (and should apply corresponding CSS), which can block an interaction in your game. We advise you to explicitely disable ":hover" effects when your game is running on a touchscreen device. * Mouseover events : like the previous one : if you associated Javascript events to "onmouseover" event, it won't work on tablets. * Drag'n'drop : it won't work. To make it work, you should listen to "ontouchstart", "ontouchmove" and "ontouchend" event and trigger the same logic you already have for "onmousedown", "onmousemove" and "onmouseup". You should also make sure to stop the Javascript "ontouchmove" event (ex: dojo.stopEvent( evt ) ) during the drag n drop, otherwise the interface is going to scroll while drag'n'droping. 946cdb0ac9ab6da15581ecafb511ad0e7c881a1f 1713 1712 2015-12-26T12:01:48Z Sourisdudesert 1 wikitext text/x-wiki Board Game Arena is now adaptated for Mobiles and Tablets too. This is very easy to have a mobile version of the game you developed with BGA Studio. In fact, your game is probably already 100% playable on mobile. However, to provide your players the best experience, you should follow the 2 advices below. == Declare your interface minimum width == By default, your game can run in an window up to 740 pixels width. Considering the informations of the right column (player's panel), it fits on a 1024px wide screen. However, you can choose to declare that your game is able to run with a smaller width. This way, the game will appear much better on mobile and tablets. For example, Reversi board is only 550px wide. If we stay with the default width (740px), the game interface displayed on mobile will be too large and some space will be lost on the left and on the right. Consequently the Reversi board is going to appear very small on the mobile screen, and players will have to "pinch & zoom" to display it correctly. To avoid that, we can specify that the game can be played with an interface with a minimum width of 550 pixels, by adding the following to gameinfos.inc.php : // Game interface width range (pixels) // Note: game interface = space on the left side, without the column on the right 'game_interface_width' => array( // Minimum width // default: 760 // maximum possible value: 760 (ie: your game interface should fit with a 760px width (correspond to a 1024px screen) // minimum possible value: 320 (the lowest value you specify, the better the display is on mobile) 'min' => 540, // Maximum width // default: null (ie: no limit, the game interface is as big as the player's screen allows it). // maximum possible value: unlimited // minimum possible value: 760 'max' => null ), == Touchscreen compatibility == Most of your game should work with touchscreen device. Note : When your game is running on a touchscreen device, the global CSS class "touch-device" is added to the root HTML element (and "notouch-device" is added in the contrary). What may not work : * ":hover" CSS switch. Because there is no mouse, ":hover" won't be triggered. This is not an issue unless it is needed to play the game. In addition, some touch device considers that a short touch must trigger a ":hover" (and should apply corresponding CSS), which can block an interaction in your game. We advise you to explicitely disable ":hover" effects when your game is running on a touchscreen device. * Mouseover events : like the previous one : if you associated Javascript events to "onmouseover" event, it won't work on tablets. * Drag'n'drop : it won't work. To make it work, you should listen to "ontouchstart", "ontouchmove" and "ontouchend" event and trigger the same logic you already have for "onmousedown", "onmousemove" and "onmouseup". You should also make sure to stop the Javascript "ontouchmove" event (ex: dojo.stopEvent( evt ) ) during the drag n drop, otherwise the interface is going to scroll while drag'n'droping. 2446cc9f894c3130e1ce190162bbcf929cdb3629 1714 1713 2015-12-26T12:11:10Z Sourisdudesert 1 /* Declare your interface minimum width */ wikitext text/x-wiki Board Game Arena is now adaptated for Mobiles and Tablets too. This is very easy to have a mobile version of the game you developed with BGA Studio. In fact, your game is probably already 100% playable on mobile. However, to provide your players the best experience, you should follow the 2 advices below. == Declare your interface minimum width == By default, your game can run in an window up to 740 pixels width. Considering the informations of the right column (player's panel), it fits on a 1024px wide screen. However, you can choose to declare that your game is able to run with a smaller width. This way, the game will appear much better on mobile and tablets. For example, Reversi board is only 540px wide. If we stay with the default width (740px), the game interface displayed on mobile will be too large and some space will be lost on the left and on the right. Consequently the Reversi board is going to appear very small on the mobile screen, and players will have to "pinch & zoom" to display it correctly. To avoid that, we can specify that the game can be played with an interface with a minimum width of 540 pixels, by adding the following to gameinfos.inc.php : // Game interface width range (pixels) // Note: game interface = space on the left side, without the column on the right 'game_interface_width' => array( // Minimum width // default: 760 // maximum possible value: 760 (ie: your game interface should fit with a 760px width (correspond to a 1024px screen) // minimum possible value: 320 (the lowest value you specify, the better the display is on mobile) 'min' => 540, // Maximum width // default: null (ie: no limit, the game interface is as big as the player's screen allows it). // maximum possible value: unlimited // minimum possible value: 760 'max' => null ), And that's it! Now, BGA can choose the better display for your game interface, whatever the device. '''Important''' If you declare that your interface can run with a 540 pixels width, it must effectively run on an interface with 540 pixels width. == Touchscreen compatibility == Most of your game should work with touchscreen device. Note : When your game is running on a touchscreen device, the global CSS class "touch-device" is added to the root HTML element (and "notouch-device" is added in the contrary). What may not work : * ":hover" CSS switch. Because there is no mouse, ":hover" won't be triggered. This is not an issue unless it is needed to play the game. In addition, some touch device considers that a short touch must trigger a ":hover" (and should apply corresponding CSS), which can block an interaction in your game. We advise you to explicitely disable ":hover" effects when your game is running on a touchscreen device. * Mouseover events : like the previous one : if you associated Javascript events to "onmouseover" event, it won't work on tablets. * Drag'n'drop : it won't work. To make it work, you should listen to "ontouchstart", "ontouchmove" and "ontouchend" event and trigger the same logic you already have for "onmousedown", "onmousemove" and "onmouseup". You should also make sure to stop the Javascript "ontouchmove" event (ex: dojo.stopEvent( evt ) ) during the drag n drop, otherwise the interface is going to scroll while drag'n'droping. 0a98b0ddbc3f7fbb0f3d8214a06d20f2bfd9f199 1715 1714 2015-12-26T12:17:39Z Sourisdudesert 1 /* Declare your interface minimum width */ wikitext text/x-wiki Board Game Arena is now adaptated for Mobiles and Tablets too. This is very easy to have a mobile version of the game you developed with BGA Studio. In fact, your game is probably already 100% playable on mobile. However, to provide your players the best experience, you should follow the 2 advices below. == Declare your interface minimum width == By default, your game can run in an window up to 740 pixels width. Considering the informations of the right column (player's panel), it fits on a 1024px wide screen. However, you can choose to declare that your game is able to run with a smaller width. This way, the game will appear much better on mobile and tablets. For example, Reversi board is only 540px wide. If we stay with the default width (740px), the game interface displayed on mobile will be too large and some space will be lost on the left and on the right. Consequently the Reversi board is going to appear very small on the mobile screen, and players will have to "pinch & zoom" to display it correctly. To avoid that, we can specify that the game can be played with an interface with a minimum width of 540 pixels, by adding the following to gameinfos.inc.php : // Game interface width range (pixels) // Note: game interface = space on the left side, without the column on the right 'game_interface_width' => array( // Minimum width // default: 760 // maximum possible value: 760 (ie: your game interface should fit with a 760px width (correspond to a 1024px screen) // minimum possible value: 320 (the lowest value you specify, the better the display is on mobile) 'min' => 540, // Maximum width // default: null (ie: no limit, the game interface is as big as the player's screen allows it). // maximum possible value: unlimited // minimum possible value: 760 'max' => null ), And that's it! Now, BGA can choose the better display for your game interface, whatever the device. '''Important''' If you declare that your interface can run with a 540 pixels width, it must effectively run on an interface with 540 pixels width. Note that it doesn't mean that your interface must ALWAYS be 540 pixels width : you just have to make your interface fluid and/or to use CSS media query to fit in any width. Examples : * On Can't Stop, when the screen is too wide, we move the dices on another position (below the main board) to fit in the width : @media only screen and (max-width: 990px) { #dicechoices { left: 180px; top: 530px; } #cantstop_wrap { height: 900px; width: 550px; } } * On Seasons, we have some panels on the right of the boards. On small screen, we display these panels below : @media only screen and (max-width: 970px) { #board { float: none; margin: auto; } .seasons_rightpanel { margin-left: 0px; } } == Touchscreen compatibility == Most of your game should work with touchscreen device. Note : When your game is running on a touchscreen device, the global CSS class "touch-device" is added to the root HTML element (and "notouch-device" is added in the contrary). What may not work : * ":hover" CSS switch. Because there is no mouse, ":hover" won't be triggered. This is not an issue unless it is needed to play the game. In addition, some touch device considers that a short touch must trigger a ":hover" (and should apply corresponding CSS), which can block an interaction in your game. We advise you to explicitely disable ":hover" effects when your game is running on a touchscreen device. * Mouseover events : like the previous one : if you associated Javascript events to "onmouseover" event, it won't work on tablets. * Drag'n'drop : it won't work. To make it work, you should listen to "ontouchstart", "ontouchmove" and "ontouchend" event and trigger the same logic you already have for "onmousedown", "onmousemove" and "onmouseup". You should also make sure to stop the Javascript "ontouchmove" event (ex: dojo.stopEvent( evt ) ) during the drag n drop, otherwise the interface is going to scroll while drag'n'droping. 0c76cb6a511a645bdfe60c6f8fd57e260f1e6756 1716 1715 2015-12-26T12:18:01Z Sourisdudesert 1 wikitext text/x-wiki Board Game Arena is now adaptated for Mobiles and Tablets too. This is very easy to have a mobile version of the game you developed with BGA Studio. In fact, your game is probably already 100% playable on mobile. However, to provide your players the best experience, you should follow the 2 advices below. == Declare your interface minimum width == By default, your game can run in an window up to 740 pixels width. Considering the informations of the right column (player's panel), it fits on a 1024px wide screen. However, you can choose to declare that your game is able to run with a smaller width. This way, the game will appear much better on mobile and tablets. For example, Reversi board is only 540px wide. If we stay with the default width (740px), the game interface displayed on mobile will be too large and some space will be lost on the left and on the right. Consequently the Reversi board is going to appear very small on the mobile screen, and players will have to "pinch & zoom" to display it correctly. To avoid that, we can specify that the game can be played with an interface with a minimum width of 540 pixels, by adding the following to gameinfos.inc.php : // Game interface width range (pixels) // Note: game interface = space on the left side, without the column on the right 'game_interface_width' => array( // Minimum width // default: 760 // maximum possible value: 760 (ie: your game interface should fit with a 760px width (correspond to a 1024px screen) // minimum possible value: 320 (the lowest value you specify, the better the display is on mobile) 'min' => 540, // Maximum width // default: null (ie: no limit, the game interface is as big as the player's screen allows it). // maximum possible value: unlimited // minimum possible value: 760 'max' => null ), And that's it! Now, BGA can choose the better display for your game interface, whatever the device. '''Important''' If you declare that your interface can run with a 540 pixels width, it must effectively run on an interface with 540 pixels width. Note that it doesn't mean that your interface must ALWAYS be 540 pixels width : you just have to make your interface fluid and/or to use CSS media query to fit in any width. Examples : * On Can't Stop, when the screen is too wide, we move the dices on another position (below the main board) to fit in the width : @media only screen and (max-width: 990px) { #dicechoices { left: 180px; top: 530px; } #cantstop_wrap { height: 900px; width: 550px; } } * On Seasons, we have some panels on the right of the boards. On small screen, we display these panels below : @media only screen and (max-width: 970px) { #board { float: none; margin: auto; } .seasons_rightpanel { margin-left: 0px; } } == Touchscreen compatibility == Most of your game should work with touchscreen device. Note : When your game is running on a touchscreen device, the global CSS class "touch-device" is added to the root HTML element (and "notouch-device" is added in the contrary). What may not work : * ":hover" CSS switch. Because there is no mouse, ":hover" won't be triggered. This is not an issue unless it is needed to play the game. In addition, some touch device considers that a short touch must trigger a ":hover" (and should apply corresponding CSS), which can block an interaction in your game. We advise you to explicitely disable ":hover" effects when your game is running on a touchscreen device. * Mouseover events : like the previous one : if you associated Javascript events to "onmouseover" event, it won't work on tablets. * Drag'n'drop : it won't work. To make it work, you should listen to "ontouchstart", "ontouchmove" and "ontouchend" event and trigger the same logic you already have for "onmousedown", "onmousemove" and "onmouseup". You should also make sure to stop the Javascript "ontouchmove" event (ex: dojo.stopEvent( evt ) ) during the drag n drop, otherwise the interface is going to scroll while drag'n'droping. f8166f1a05ff1dcf85bcef9f461b68edf4475f71 1717 1716 2015-12-26T12:20:24Z Sourisdudesert 1 wikitext text/x-wiki Board Game Arena is now adaptated for Mobiles and Tablets too. This is very easy to have a mobile version of the game you developed with BGA Studio. In fact, your game is probably already 100% playable on mobile. However, to provide your players the best experience, you should follow the 2 advices below. == Declare your interface minimum width == By default, your game can run in an window up to 740 pixels width. Considering the informations of the right column (player's panel), it fits on a 1024px wide screen. However, you can choose to declare that your game is able to run with a smaller width. This way, the game will appear much better on mobile and tablets. For example, Reversi board is only 540px wide. If we stay with the default width (740px), the game interface displayed on mobile will be too large and some space will be lost on the left and on the right. Consequently the Reversi board is going to appear very small on the mobile screen, and players will have to "pinch & zoom" to display it correctly. To avoid that, we can specify that the game can be played with an interface with a minimum width of 540 pixels, by adding the following to gameinfos.inc.php : // Game interface width range (pixels) // Note: game interface = space on the left side, without the column on the right 'game_interface_width' => array( // Minimum width // default: 760 // maximum possible value: 760 (ie: your game interface should fit with a 760px width (correspond to a 1024px screen) // minimum possible value: 320 (the lowest value you specify, the better the display is on mobile) 'min' => 540, // Maximum width // default: null (ie: no limit, the game interface is as big as the player's screen allows it). // maximum possible value: unlimited // minimum possible value: 760 'max' => null ), And that's it! Now, BGA can choose the better display for your game interface, whatever the device. '''Important''' If you declare that your interface can run with a 540 pixels width, it must effectively run on an interface with 540 pixels width. Note that it doesn't mean that your interface must ALWAYS be 540 pixels width : you just have to make your interface fluid and/or to use CSS media query to fit in any width. Examples : * On Can't Stop, when the screen is too wide, we move the dices on another position (below the main board) to fit in the width : @media only screen and (max-width: 990px) { #dicechoices { left: 180px; top: 530px; } #cantstop_wrap { height: 900px; width: 550px; } } * On Seasons, we have some panels on the right of the boards. On small screen, we display these panels below : @media only screen and (max-width: 970px) { #board { float: none; margin: auto; } .seasons_rightpanel { margin-left: 0px; } } Tips : on mobile, BGA displays players' panels at the top of the page (instead of displaying them on the right). When doing this, BGA applies the CSS class "mobile_version" to the root HTML element. If you want you can use this CSS "mobile_version" class to synchronize some of your game adaptations to this change. == Touchscreen compatibility == Most of your game should work with touchscreen device. Note : When your game is running on a touchscreen device, the global CSS class "touch-device" is added to the root HTML element (and "notouch-device" is added in the contrary). What may not work : * ":hover" CSS switch. Because there is no mouse, ":hover" won't be triggered. This is not an issue unless it is needed to play the game. In addition, some touch device considers that a short touch must trigger a ":hover" (and should apply corresponding CSS), which can block an interaction in your game. We advise you to explicitely disable ":hover" effects when your game is running on a touchscreen device. * Mouseover events : like the previous one : if you associated Javascript events to "onmouseover" event, it won't work on tablets. * Drag'n'drop : it won't work. To make it work, you should listen to "ontouchstart", "ontouchmove" and "ontouchend" event and trigger the same logic you already have for "onmousedown", "onmousemove" and "onmouseup". You should also make sure to stop the Javascript "ontouchmove" event (ex: dojo.stopEvent( evt ) ) during the drag n drop, otherwise the interface is going to scroll while drag'n'droping. 60c02c182cfde1e37950d26a29bca0e0c6fd3e27 1718 1717 2015-12-27T11:30:35Z Een 3 wikitext text/x-wiki Board Game Arena is now adaptated for Mobiles and Tablets too. It is very easy to have a mobile version of the game you developed with BGA Studio. In fact, your game is probably already 100% playable on mobile. However, to provide your players the best experience, you should follow the 2 advices below. == Declare your interface minimum width == By default, your game can run in an window up to 740 pixels width. Considering the informations of the right column (player's panel), it fits on a 1024px wide screen. However, you can choose to declare that your game is able to run with a smaller width. This way, the game will appear much better on mobile and tablets. For example, Reversi board is only 540px wide. If we stay with the default width (740px), the game interface displayed on mobile will be too large and some space will be lost on the left and on the right. Consequently the Reversi board is going to appear very small on the mobile screen, and players will have to "pinch & zoom" to display it correctly. To avoid that, we can specify that the game can be played with an interface with a minimum width of 540 pixels, by adding the following to gameinfos.inc.php : // Game interface width range (pixels) // Note: game interface = space on the left side, without the column on the right 'game_interface_width' => array( // Minimum width // default: 760 // maximum possible value: 760 (ie: your game interface should fit with a 760px width (correspond to a 1024px screen) // minimum possible value: 320 (the lowest value you specify, the better the display is on mobile) 'min' => 540, // Maximum width // default: null (ie: no limit, the game interface is as big as the player's screen allows it). // maximum possible value: unlimited // minimum possible value: 760 'max' => null ), And that's it! Now, BGA can choose the better display for your game interface, whatever the device. '''Important''' If you declare that your interface can run with a 540 pixels width, it must effectively run on an interface with 540 pixels width. Note that it doesn't mean that your interface must ALWAYS be 540 pixels width : you just have to make your interface fluid and/or to use CSS media query to fit in any width. Examples : * On Can't Stop, when the screen is too wide, we move the dices on another position (below the main board) to fit in the width : @media only screen and (max-width: 990px) { #dicechoices { left: 180px; top: 530px; } #cantstop_wrap { height: 900px; width: 550px; } } * On Seasons, we have some panels on the right of the boards. On small screen, we display these panels below : @media only screen and (max-width: 970px) { #board { float: none; margin: auto; } .seasons_rightpanel { margin-left: 0px; } } Tips : on mobile, BGA displays players' panels at the top of the page (instead of displaying them on the right). When doing this, BGA applies the CSS class "mobile_version" to the root HTML element. If you want you can use this CSS "mobile_version" class to synchronize some of your game adaptations to this change. == Touchscreen compatibility == Most of your game should work with touchscreen device. Note : When your game is running on a touchscreen device, the global CSS class "touch-device" is added to the root HTML element (and "notouch-device" is added in the contrary). What may not work : * ":hover" CSS switch. Because there is no mouse, ":hover" won't be triggered. This is not an issue unless it is needed to play the game. In addition, some touch device considers that a short touch must trigger a ":hover" (and should apply corresponding CSS), which can block an interaction in your game. We advise you to explicitely disable ":hover" effects when your game is running on a touchscreen device. * Mouseover events : like the previous one : if you associated Javascript events to "onmouseover" event, it won't work on tablets. * Drag'n'drop : it won't work. To make it work, you should listen to "ontouchstart", "ontouchmove" and "ontouchend" event and trigger the same logic you already have for "onmousedown", "onmousemove" and "onmouseup". You should also make sure to stop the Javascript "ontouchmove" event (ex: dojo.stopEvent( evt ) ) during the drag n drop, otherwise the interface is going to scroll while drag'n'droping. 425d62e170c057252b6c3388215486a24f3a8f49 1719 1718 2015-12-27T12:05:13Z Een 3 wikitext text/x-wiki Board Game Arena is now adaptated for Mobiles and Tablets too. It is very easy to have a mobile version of the game you developed with BGA Studio. In fact, your game is probably already 100% playable on mobile. However, to provide your players the best experience, you should follow the 2 advices below. == Declare your interface minimum width == By default, your game can run in an window up to 740 pixels width. Considering the informations of the right column (player's panel), it fits on a 1024px wide screen. However, you can choose to declare that your game is able to run with a smaller width. This way, the game will appear much better on mobile and tablets. For example, Reversi board is only 540px wide. If we stay with the default width (740px), the game interface displayed on mobile will be too large and some space will be lost on the left and on the right. Consequently the Reversi board is going to appear very small on the mobile screen, and players will have to "pinch & zoom" to display it correctly. To avoid that, we can specify that the game can be played with an interface with a minimum width of 540 pixels, by adding the following to gameinfos.inc.php : // Game interface width range (pixels) // Note: game interface = space on the left side, without the column on the right 'game_interface_width' => array( // Minimum width // default: 760 // maximum possible value: 760 (ie: your game interface should fit with a 760px width (correspond to a 1024px screen) // minimum possible value: 320 (the lowest value you specify, the better the display is on mobile) 'min' => 540, // Maximum width // default: null (ie: no limit, the game interface is as big as the player's screen allows it). // maximum possible value: unlimited // minimum possible value: 760 'max' => null ), And that's it! Now, BGA can choose the better display for your game interface, whatever the device. '''Important''' If you declare that your interface can run with a 540 pixels width, it must effectively run on an interface with 540 pixels width. Note that this doesn't mean that your interface must ALWAYS be 540 pixels width: you just have to make your interface fluid and/or to use CSS media query to fit in any width. Examples : * On Can't Stop, when the screen is too wide, we move the dices on another position (below the main board) to fit in the width : @media only screen and (max-width: 990px) { #dicechoices { left: 180px; top: 530px; } #cantstop_wrap { height: 900px; width: 550px; } } * On Seasons, we have some panels on the right of the board. On small screens, we display these panels below the board: @media only screen and (max-width: 970px) { #board { float: none; margin: auto; } .seasons_rightpanel { margin-left: 0px; } } Tip: on mobile, BGA displays player panels at the top of the page (instead of displaying them on the right). When doing this, BGA applies the CSS class "mobile_version" to the root HTML element. If you want you can use this CSS "mobile_version" class to optimize some of your game adaptations to this change. == Touchscreen compatibility == Most of your games should work with touchscreen devices without needing any changes. Note: when your game is running on a touchscreen device, the global CSS class "touch-device" is added to the root HTML element (and "notouch-device" is added for the opposite). What may not work : * ":hover" CSS switch. Because there is no mouse, ":hover" won't be triggered. This is not an issue unless it is needed to play the game. In addition, some touch devices consider that a short touch must trigger a ":hover" (and should apply corresponding CSS), which can block an interaction in your game. We advise you to explicitely disable ":hover" effects when your game is running on a touchscreen device. * Mouseover events : like the previous one : if you associated Javascript events to "onmouseover" event, it won't work on tablets. * Drag'n'drop : it won't work. To make it work, you should listen to "ontouchstart", "ontouchmove" and "ontouchend" event and trigger the same logic you already have for "onmousedown", "onmousemove" and "onmouseup". You should also make sure to stop the Javascript "ontouchmove" event (ex: dojo.stopEvent( evt ) ) during the drag n drop, otherwise the interface is going to scroll while drag'n'dropping. 382c2055ad6d3f2b0297db4641eacba86c06a5b1 1720 1719 2015-12-28T10:24:07Z Sourisdudesert 1 wikitext text/x-wiki Board Game Arena is now adaptated for Mobiles and Tablets too. It is very easy to have a mobile version of the game you developed with BGA Studio. In fact, your game is probably already 100% playable on mobile. However, to provide your players the best experience, you should follow the 2 advices below. == Declare your interface minimum width == By default, your game can run in an window up to 740 pixels width. Considering the informations of the right column (player's panel), it fits on a 1024px wide screen. However, you can choose to declare that your game is able to run with a smaller width. This way, the game will appear much better on mobile and tablets. For example, Reversi board is only 540px wide. If we stay with the default width (740px), the game interface displayed on mobile will be too large and some space will be lost on the left and on the right. Consequently the Reversi board is going to appear very small on the mobile screen, and players will have to "pinch & zoom" to display it correctly. To avoid that, we can specify that the game can be played with an interface with a minimum width of 540 pixels, by adding the following to gameinfos.inc.php : // Game interface width range (pixels) // Note: game interface = space on the left side, without the column on the right 'game_interface_width' => array( // Minimum width // default: 740 // maximum possible value: 740 (ie: your game interface should fit with a 740px width (correspond to a 1024px screen) // minimum possible value: 320 (the lowest value you specify, the better the display is on mobile) 'min' => 540, // Maximum width // default: null (ie: no limit, the game interface is as big as the player's screen allows it). // maximum possible value: unlimited // minimum possible value: 740 'max' => null ), And that's it! Now, BGA can choose the better display for your game interface, whatever the device. '''Important''' If you declare that your interface can run with a 540 pixels width, it must effectively run on an interface with 540 pixels width. Note that this doesn't mean that your interface must ALWAYS be 540 pixels width: you just have to make your interface fluid and/or to use CSS media query to fit in any width. Examples : * On Can't Stop, when the screen is too wide, we move the dices on another position (below the main board) to fit in the width : @media only screen and (max-width: 990px) { #dicechoices { left: 180px; top: 530px; } #cantstop_wrap { height: 900px; width: 550px; } } * On Seasons, we have some panels on the right of the board. On small screens, we display these panels below the board: @media only screen and (max-width: 970px) { #board { float: none; margin: auto; } .seasons_rightpanel { margin-left: 0px; } } Tip: on mobile, BGA displays player panels at the top of the page (instead of displaying them on the right). When doing this, BGA applies the CSS class "mobile_version" to the root HTML element. If you want you can use this CSS "mobile_version" class to optimize some of your game adaptations to this change. == Touchscreen compatibility == Most of your games should work with touchscreen devices without needing any changes. Note: when your game is running on a touchscreen device, the global CSS class "touch-device" is added to the root HTML element (and "notouch-device" is added for the opposite). What may not work : * ":hover" CSS switch. Because there is no mouse, ":hover" won't be triggered. This is not an issue unless it is needed to play the game. In addition, some touch devices consider that a short touch must trigger a ":hover" (and should apply corresponding CSS), which can block an interaction in your game. We advise you to explicitely disable ":hover" effects when your game is running on a touchscreen device. * Mouseover events : like the previous one : if you associated Javascript events to "onmouseover" event, it won't work on tablets. * Drag'n'drop : it won't work. To make it work, you should listen to "ontouchstart", "ontouchmove" and "ontouchend" event and trigger the same logic you already have for "onmousedown", "onmousemove" and "onmouseup". You should also make sure to stop the Javascript "ontouchmove" event (ex: dojo.stopEvent( evt ) ) during the drag n drop, otherwise the interface is going to scroll while drag'n'dropping. 5088bc7284d1f0063f007ef2a3a8e41fdf8ef49b 1721 1720 2015-12-28T10:26:09Z Sourisdudesert 1 /* Declare your interface minimum width */ wikitext text/x-wiki Board Game Arena is now adaptated for Mobiles and Tablets too. It is very easy to have a mobile version of the game you developed with BGA Studio. In fact, your game is probably already 100% playable on mobile. However, to provide your players the best experience, you should follow the 2 advices below. == Declare your interface minimum width == By default, your game can run in an window up to 740 pixels width. Considering the informations of the right column (player's panel), it fits on a 1024px wide screen. However, you can choose to declare that your game is able to run with a smaller width. This way, the game will appear much better on mobile and tablets. For example, Reversi board is only 540px wide. If we stay with the default width (740px), the game interface displayed on mobile will be too large and some space will be lost on the left and on the right. Consequently the Reversi board is going to appear very small on the mobile screen, and players will have to "pinch & zoom" to display it correctly. To avoid that, we can specify that the game can be played with an interface with a minimum width of 540 pixels, by adding the following to gameinfos.inc.php : // Game interface width range (pixels) // Note: game interface = space on the left side, without the column on the right 'game_interface_width' => array( // Minimum width // default: 740 // maximum possible value: 740 (ie: your game interface should fit with a 740px width (correspond to a 1024px screen) // minimum possible value: 320 (the lowest value you specify, the better the display is on mobile) 'min' => 540, // Maximum width // default: null (ie: no limit, the game interface is as big as the player's screen allows it). // maximum possible value: unlimited // minimum possible value: 740 'max' => null ), And that's it! Now, BGA can choose the better display for your game interface, whatever the device. '''Important''' If you declare that your interface can run with a 540 pixels width, it must effectively run on an interface with 540 pixels width. Note that this doesn't mean that your interface must ALWAYS be 540 pixels width: you just have to make your interface fluid and/or to use CSS media query to fit in any width. Examples : * On Can't Stop, when the screen is too narrow, we move the dices on another position (below the main board) to fit in the width : @media only screen and (max-width: 990px) { #dicechoices { left: 180px; top: 530px; } #cantstop_wrap { height: 900px; width: 550px; } } * On Seasons, we have some panels on the right of the board. On small screens, we display these panels below the board: @media only screen and (max-width: 970px) { #board { float: none; margin: auto; } .seasons_rightpanel { margin-left: 0px; } } Tip: on mobile, BGA displays player panels at the top of the page (instead of displaying them on the right). When doing this, BGA applies the CSS class "mobile_version" to the root HTML element. If you want you can use this CSS "mobile_version" class to optimize some of your game adaptations to this change. == Touchscreen compatibility == Most of your games should work with touchscreen devices without needing any changes. Note: when your game is running on a touchscreen device, the global CSS class "touch-device" is added to the root HTML element (and "notouch-device" is added for the opposite). What may not work : * ":hover" CSS switch. Because there is no mouse, ":hover" won't be triggered. This is not an issue unless it is needed to play the game. In addition, some touch devices consider that a short touch must trigger a ":hover" (and should apply corresponding CSS), which can block an interaction in your game. We advise you to explicitely disable ":hover" effects when your game is running on a touchscreen device. * Mouseover events : like the previous one : if you associated Javascript events to "onmouseover" event, it won't work on tablets. * Drag'n'drop : it won't work. To make it work, you should listen to "ontouchstart", "ontouchmove" and "ontouchend" event and trigger the same logic you already have for "onmousedown", "onmousemove" and "onmouseup". You should also make sure to stop the Javascript "ontouchmove" event (ex: dojo.stopEvent( evt ) ) during the drag n drop, otherwise the interface is going to scroll while drag'n'dropping. 2b29a017a67d3eeafa183e3ed3b401c3a07c958e 1722 1721 2015-12-28T10:32:35Z Sourisdudesert 1 wikitext text/x-wiki Board Game Arena is now adaptated for Mobiles and Tablets too. It is very easy to have a mobile version of the game you developed with BGA Studio. In fact, your game is probably already 100% playable on mobile. However, to provide your players the best experience, you should follow the 2 advices below. == Declare your interface minimum width == By default, your game can run in an window up to 740 pixels width. Considering the informations of the right column (player's panel), it fits on a 1024px wide screen. However, you can choose to declare that your game is able to run with a smaller width. This way, the game will appear much better on mobile and tablets. For example, Reversi board is only 540px wide. If we stay with the default width (740px), the game interface displayed on mobile will be too large and some space will be lost on the left and on the right. Consequently the Reversi board is going to appear very small on the mobile screen, and players will have to "pinch & zoom" to display it correctly. To avoid that, we can specify that the game can be played with an interface with a minimum width of 540 pixels, by adding the following to gameinfos.inc.php : // Game interface width range (pixels) // Note: game interface = space on the left side, without the column on the right 'game_interface_width' => array( // Minimum width // default: 740 // maximum possible value: 740 (ie: your game interface should fit with a 740px width (correspond to a 1024px screen) // minimum possible value: 320 (the lowest value you specify, the better the display is on mobile) 'min' => 540, // Maximum width // default: null (ie: no limit, the game interface is as big as the player's screen allows it). // maximum possible value: unlimited // minimum possible value: 740 'max' => null ), And that's it! Now, BGA can choose the better display for your game interface, whatever the device. '''Important''' If you declare that your interface can run with a 540 pixels width, it must effectively run on an interface with 540 pixels width. Note that this doesn't mean that your interface must ALWAYS be 540 pixels width: you just have to make your interface fluid and/or to use CSS media query to fit in any width. Examples : * On Can't Stop, when the screen is too narrow, we move the dices on another position (below the main board) to fit in the width : @media only screen and (max-width: 990px) { #dicechoices { left: 180px; top: 530px; } #cantstop_wrap { height: 900px; width: 550px; } } * On Seasons, we have some panels on the right of the board. On small screens, we display these panels below the board: @media only screen and (max-width: 970px) { #board { float: none; margin: auto; } .seasons_rightpanel { margin-left: 0px; } } Tip: on mobile, BGA displays player panels at the top of the page (instead of displaying them on the right). When doing this, BGA applies the CSS class "mobile_version" to the root HTML element with id "ebd-body". If you want you can use this CSS "mobile_version" class to optimize some of your game adaptations to this change. In the opposite, when the "normal" version is active, the CSS class "desktop_version" BGA applies the CSS class "desktop_version" to the root HTML element with id "ebd-body". == Touchscreen compatibility == Most of your games should work with touchscreen devices without needing any changes. Note: when your game is running on a touchscreen device, the global CSS class "touch-device" is added to the to the root HTML element with id "ebd-body" (and "notouch-device" is added for the opposite). What may not work : * ":hover" CSS switch. Because there is no mouse, ":hover" won't be triggered. This is not an issue unless it is needed to play the game. In addition, some touch devices consider that a short touch must trigger a ":hover" (and should apply corresponding CSS), which can block an interaction in your game. We advise you to explicitely disable ":hover" effects when your game is running on a touchscreen device. * Mouseover events : like the previous one : if you associated Javascript events to "onmouseover" event, it won't work on tablets. * Drag'n'drop : it won't work. To make it work, you should listen to "ontouchstart", "ontouchmove" and "ontouchend" event and trigger the same logic you already have for "onmousedown", "onmousemove" and "onmouseup". You should also make sure to stop the Javascript "ontouchmove" event (ex: dojo.stopEvent( evt ) ) during the drag n drop, otherwise the interface is going to scroll while drag'n'dropping. f0ba4f75d6578029d21440a78f9ef76d2a230e9a 1725 1722 2015-12-29T08:12:59Z Sourisdudesert 1 /* Touchscreen compatibility */ wikitext text/x-wiki Board Game Arena is now adaptated for Mobiles and Tablets too. It is very easy to have a mobile version of the game you developed with BGA Studio. In fact, your game is probably already 100% playable on mobile. However, to provide your players the best experience, you should follow the 2 advices below. == Declare your interface minimum width == By default, your game can run in an window up to 740 pixels width. Considering the informations of the right column (player's panel), it fits on a 1024px wide screen. However, you can choose to declare that your game is able to run with a smaller width. This way, the game will appear much better on mobile and tablets. For example, Reversi board is only 540px wide. If we stay with the default width (740px), the game interface displayed on mobile will be too large and some space will be lost on the left and on the right. Consequently the Reversi board is going to appear very small on the mobile screen, and players will have to "pinch & zoom" to display it correctly. To avoid that, we can specify that the game can be played with an interface with a minimum width of 540 pixels, by adding the following to gameinfos.inc.php : // Game interface width range (pixels) // Note: game interface = space on the left side, without the column on the right 'game_interface_width' => array( // Minimum width // default: 740 // maximum possible value: 740 (ie: your game interface should fit with a 740px width (correspond to a 1024px screen) // minimum possible value: 320 (the lowest value you specify, the better the display is on mobile) 'min' => 540, // Maximum width // default: null (ie: no limit, the game interface is as big as the player's screen allows it). // maximum possible value: unlimited // minimum possible value: 740 'max' => null ), And that's it! Now, BGA can choose the better display for your game interface, whatever the device. '''Important''' If you declare that your interface can run with a 540 pixels width, it must effectively run on an interface with 540 pixels width. Note that this doesn't mean that your interface must ALWAYS be 540 pixels width: you just have to make your interface fluid and/or to use CSS media query to fit in any width. Examples : * On Can't Stop, when the screen is too narrow, we move the dices on another position (below the main board) to fit in the width : @media only screen and (max-width: 990px) { #dicechoices { left: 180px; top: 530px; } #cantstop_wrap { height: 900px; width: 550px; } } * On Seasons, we have some panels on the right of the board. On small screens, we display these panels below the board: @media only screen and (max-width: 970px) { #board { float: none; margin: auto; } .seasons_rightpanel { margin-left: 0px; } } Tip: on mobile, BGA displays player panels at the top of the page (instead of displaying them on the right). When doing this, BGA applies the CSS class "mobile_version" to the root HTML element with id "ebd-body". If you want you can use this CSS "mobile_version" class to optimize some of your game adaptations to this change. In the opposite, when the "normal" version is active, the CSS class "desktop_version" BGA applies the CSS class "desktop_version" to the root HTML element with id "ebd-body". == Touchscreen compatibility == Most of your games should work with touchscreen devices without needing any changes. Note: when your game is running on a touchscreen device, the global CSS class "touch-device" is added to the to the root HTML element with id "ebd-body" (and "notouch-device" is added for the opposite). What may not work : * ":hover" CSS switch. Because there is no mouse, ":hover" won't be triggered. This is not an issue unless it is needed to play the game. In addition, some touch devices consider that a short touch must trigger a ":hover" (and should apply corresponding CSS), which can block an interaction in your game. We advise you to explicitely disable ":hover" effects when your game is running on a touchscreen device (for ex. by adding ".notouch-device" as a prefix to all your CSS :hover rules). * Mouseover events : like the previous one : if you associated Javascript events to "onmouseover" event, it won't work on tablets. * Drag'n'drop : it won't work. To make it work, you should listen to "ontouchstart", "ontouchmove" and "ontouchend" event and trigger the same logic you already have for "onmousedown", "onmousemove" and "onmouseup". You should also make sure to stop the Javascript "ontouchmove" event (ex: dojo.stopEvent( evt ) ) during the drag n drop, otherwise the interface is going to scroll while drag'n'dropping. c8ff3baa9f1f9e5a8cea5f1950ead30d3c26bad7 Main game logic: yourgamename.game.php 0 86 1723 1657 2015-12-28T10:42:27Z Sourisdudesert 1 wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 79 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. Notifications sent between the game start (setupNewGame) and the end of the "action" method of the first active state will never reach their destination. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array. Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private date must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. == Player color preferences == BGA players (Club members) may now choose their preferred color for playing. For example, if they are used to play green for every board game, they can select "green" in their BGA preferences page. Making your game compatible with colors preferences is very easy and requires only 1 line of PHP and 1 configuration change : On your gameinfos.inc.php file, add the following lines : // Favorite colors support : if set to "true", support attribution of favorite colors based on player's preferences (see reattributeColorsBasedOnPreferences PHP method) 'favorite_colors_support' => true, Then, on your main <your_game>.game.php file, find the "reloadPlayersBasicInfos" call in your "setupNewGame" method and replace : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reloadPlayersBasicInfos(); By : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reattributeColorsBasedOnPreferences( $players, array( /* LIST HERE THE AVAILABLE COLORS OF YOUR GAME INSTEAD OF THESE ONES */"ff0000", "008000", "0000ff", "ffa500", "773300" ) ); self::reloadPlayersBasicInfos(); The "reattributeColorsBasedOnPreferences" method reattributes all colors, taking into account players color preferences and available colors. Note that you must update the colors to indicate the colors available for your game. 2 important remarks : * for some games (ex : Chess), the color has an influence on a mechanism of the game, most of the time by giving a special advantage to a player (ex : Starting the game). Color preference mechanism must NOT be used in such a case. * your logic should NEVER consider that the first player has the color X, that the second player has the color Y, and so on. If this is the case, your game will NOT be compatible with reattributeColorsBasedOnPreferences as this method attribute colors to players based on their preferences and not based as their order at the table. abe05cc4a26f1c9b52cfe05574cc50906fa0d478 Gamehelpquarto 0 140 1732 1005 2016-01-01T05:29:40Z Rainn 5818 added 2×2 variant rules wikitext text/x-wiki Quarto is a simple abstract game that should take about 15 mins. to play. '''To win, complete a row of 4 pieces (horizontally, vertically, or diagonally) that share at least one trait in common. The twist to the game is that you select the piece your opponent places on the board and vice versa.''' Pieces have 4 traits each which are a combination of the following: Tall or Short Dark or Light Round or Square Hollow or Solid ===Advanced (2×2) variant=== In this variant, you also win if you finish a 2×2 block of ''any'' 4 pieces -- regardless of their traits. ac7ba12e34628ded52396cd843d732d6da7827f9 1733 1732 2016-01-01T05:44:42Z Rainn 5818 /* Advanced (2×2) variant */ -- corrected the rules wikitext text/x-wiki Quarto is a simple abstract game that should take about 15 mins. to play. '''To win, complete a row of 4 pieces (horizontally, vertically, or diagonally) that share at least one trait in common. The twist to the game is that you select the piece your opponent places on the board and vice versa.''' Pieces have 4 traits each which are a combination of the following: Tall or Short Dark or Light Round or Square Hollow or Solid ===Advanced (2×2) variant=== In this variant, you also win if you finish a 2×2 block of 4 pieces that share a trait in common. 683eeadd7c8e8c94b139fcbadc8c6544efaef14f 1737 1733 2016-01-03T17:41:52Z Chaotic iak 3338 wikitext text/x-wiki Quarto is an abstract board game for 2 players. Players compete to place pieces on a 4x4 grid, to be the first player to make a line of four pieces where all of them share some characteristic. The twist is that the opponent chooses the piece to be played. == Start of the game == The board is divided into 16 spaces in a 4x4 grid. There are 16 pieces. Each piece can be light or dark, tall or short, circular or square, and solid or hollow. Each possible combination (for example, light/tall/circular/solid or dark/short/square/hollow) appears exactly once. The board starts off empty; all pieces are off the board. == Player's turn == In a player's turn, two steps happen. First, the '''opponent''' chooses a piece, then the player chooses a space to place the piece. Any piece still off the board may be selected, and any empty space may be selected. == End of the game == The game ends when there is a line of four occupied spaces, of which all four pieces in the line share a common trait (for example, all light or all short). The player that places the last piece that forms that line of four (not the opponent who selected it) is the winner. f3dbb5b55f630067d5b33716feee837fec11941c 1740 1737 2016-01-09T11:27:50Z Chaotic iak 3338 wikitext text/x-wiki Quarto is an abstract board game for 2 players. Players compete to place pieces on a 4x4 grid, to be the first player to make a line of four pieces (or in advanced variant, also a 2x2 square) where all of them share some characteristic. The twist is that the opponent chooses the piece to be played. == Start of the game == The board is divided into 16 spaces in a 4x4 grid. There are 16 pieces. Each piece can be light or dark, tall or short, circular or square, and solid or hollow. Each possible combination (for example, light/tall/circular/solid or dark/short/square/hollow) appears exactly once. The board starts off empty; all pieces are off the board. == Player's turn == In a player's turn, two steps happen. First, the '''opponent''' chooses a piece, then the player chooses a space to place the piece. Any piece still off the board may be selected, and any empty space may be selected. == End of the game == The game ends when there is a line of four occupied spaces, of which all four pieces in the line share a common trait (for example, all light or all short). The player that places the last piece that forms that line of four (not the opponent who selected it) is the winner. In the '''advanced''' variant, a 2x2 area that share a common trait also ends the game, winning for the player that places the piece. 60a3d62336e11284060473e022ede11a8834352b Translation guidelines 0 18 1734 159 2016-01-02T20:08:02Z Neon555 11014 /* I fixed some translations, but they don't appear to have changed on the site */ wikitext text/x-wiki The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena into any language, in order to enable more people to discover and play board games, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10-year-old nephew and he doesn't speak English yet, no problem! Just help us translate Board Game Arena into your language! == What can be translated? == Every string of text for the main site interface and for the games' interfaces are 'internationalized' and can be translated. For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometime later... == Who should translate? == This is important: only translate text into a given language if you are a native speaker of the language. When translating a game, the translator should know the game thoroughly and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronominal rules usual for the gaming audience of their country. As Board Game Arena's team's mother tongue is French, we will take charge of the French translations. We will also release the first version of the English translation. As we are not perfect speakers of Shakespeare's language, these translations will be open for review and correction by native English speakers under the same conditions as the other languages. == About context == Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot incorrect forms (if any) while playing and be able to correct them. Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information. == When will the site be made available in a new language it is being translated into? == As soon as a sufficient number of the strings have been translated in the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in the language. == I fixed some translations, but they don't appear to have changed on the site == Translation files are updated nightly, so you just have to wait till tomorrow for your changes to appear on the site. == How long will it be possible to change the translations? == The first translations may not be perfect (as explained in the 'about context' section). So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore. == Is there some reward for translating? == Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated). This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all! == Translation tips == * Use the 'TAB' key to go from one text box to another. This is easier than clicking. * Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}). * When in doubt, leave a comment for the next translator. * When you fix someone's translation, leave a comment if the reason for the change is not obvious. * When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing. 0bd5001ad2338ba051daae1ad55b9df7586b0dd0 1735 1734 2016-01-02T20:08:22Z Neon555 11014 /* When will the site be made available in a new language it is being translated into? */ wikitext text/x-wiki The [http://en.boardgamearena.com/#!translationhq collaborative translation system] is meant to make it possible to translate Board Game Arena into any language, in order to enable more people to discover and play board games, even when not knowing English or French. For example, if you want to play 'Dragonheart' with your 10-year-old nephew and he doesn't speak English yet, no problem! Just help us translate Board Game Arena into your language! == What can be translated? == Every string of text for the main site interface and for the games' interfaces are 'internationalized' and can be translated. For now, forum posts and articles of the website (such as this one), cannot be translated. Maybe sometime later... == Who should translate? == This is important: only translate text into a given language if you are a native speaker of the language. When translating a game, the translator should know the game thoroughly and if possible have a box and rulebook of the game in the destination language to check for consistency. Translators should take into account the level of language and the formal/informal pronominal rules usual for the gaming audience of their country. As Board Game Arena's team's mother tongue is French, we will take charge of the French translations. We will also release the first version of the English translation. As we are not perfect speakers of Shakespeare's language, these translations will be open for review and correction by native English speakers under the same conditions as the other languages. == About context == Some strings can be translated differently depending upon the context. When this is the case, you should use the most obvious translation. Then when the site has been released in your language, native speakers will spot incorrect forms (if any) while playing and be able to correct them. Also, you can ask us for context in the [http://forum.boardgamearena.com/viewforum.php?f=11 translation forum] (in English or in French), and we will try to look it up and provide the information. == When will the site be made available in a new language it is being translated into? == As soon as a sufficient number of the strings have been translated into the new language in order for the site to make sense into that language, the Board Game Area team will make the site available in the language. == I fixed some translations, but they don't appear to have changed on the site == Translation files are updated nightly, so you just have to wait till tomorrow for your changes to appear on the site. == How long will it be possible to change the translations? == The first translations may not be perfect (as explained in the 'about context' section). So they can be modified until they are 'validated'. Validation occurs when a translation has not been modified for 30 days straight. It is then considered stable and valid (golden icon) and cannot be changed anymore. == Is there some reward for translating? == Yes! Every translator that gets 100 translations validated (golden icon) will get one free month of 'Board Game Arena Club' membership (and one more month for every batch of 100 new translations validated). This is of course only a symbolic gesture of thanks for people participating in making BGA accessible to more and more people. The possibility to enjoy board games with people from many countries is the greatest reward of all! == Translation tips == * Use the 'TAB' key to go from one text box to another. This is easier than clicking. * Strings such as ${SOMETHING}, %SOMETHING, <SOMETHING> are markup strings for formatting or substituting text and must be left as is. Their position in the overall string can be changed as appropriate in a given language (for example for pronouns such as ${you}). * When in doubt, leave a comment for the next translator. * When you fix someone's translation, leave a comment if the reason for the change is not obvious. * When the translation can depend on context which is not explicit, go with the most straightforward translation. If it is not correct, it will be spotted and fixed later by native speakers while playing. 2658730c4b33d2117a17e831c1eca82c436e72a5 Gamehelpgyges 0 183 1736 1352 2016-01-03T17:33:59Z Chaotic iak 3338 wikitext text/x-wiki Gygès is an abstract board game for 2 players. Players move shared pieces on the board, bouncing off each other, vying to be the first to end a move on the opponent's goal space. == Start of the game == The board has size 6x6. Additionally, two goal spaces are on the board, each located behind the row closest to each player. The goal space is adjacent to all spaces of its closest row. There are 12 pieces in the game: four with one ring, four with two rings, and four with three rings. All pieces are shared; pieces don't belong to either player. At the beginning of the game, each player receives two pieces of each type and sets their positions on their first row. (With ''rules for beginners'' in effect, a player can select one of several predetermined patterns instead.) == Player's turn == In a player's turn, a player must move a piece. Only pieces on the first non-empty row from a player's perspective can be moved. (This means, for example, at the beginning of the game, only the six pieces a player places may be moved; the other six pieces that the opponent placed are not on the first non-empty row.) A piece must move exactly as many spaces as the number of rings on it. Intermediate spaces must be empty; however, the final space may be non-empty. If it's empty, then the move ends. If it isn't, the player gets to choose one of two possibilities: * '''Bounce''' off the piece: the player gets to move the original piece by the number of rings on the landed-on piece. For example, if a player ends the move on a 1-ring piece, the player can bounce off that piece to continue moving by exactly one space. * '''Replace''' the piece: the player stops the move on that space and moves the landed-on piece to any non-empty spot on the board. The only restriction is that the landed-on piece may not be placed behind the opponent's first non-empty row. If, after bouncing a piece, a player lands on another piece, they must keep choosing whether to bounce or to replace. Only when a player decides to end a move on an empty space or to replace a piece that the player's move ends. A piece may not travel between the same two spaces more than once in a single move. A piece may not pass through the goal space; it may only finish its move there. (The count still has to be exact; if it's impossible to finish a move on the goal space, then the goal space cannot be entered at all.) == End of the game == The game ends when a player moves a piece to land it on the opponent's goal space; this player wins. 3f2cad8e60c54671b1ad782958d05b2b42737254 Gamehelplostcities 0 210 1738 2016-01-07T06:18:49Z Nandblock 11082 Created page with "'''THE DECK:''' Each expedition (suit) contains 9 cards numbered 2-10, and 3 investment cards (handshakes). '''PLAY:''' On each player's turn, they must: 1. Either add one ..." wikitext text/x-wiki '''THE DECK:''' Each expedition (suit) contains 9 cards numbered 2-10, and 3 investment cards (handshakes). '''PLAY:''' On each player's turn, they must: 1. Either add one card to an expedition (suit) or discard one to the appropriate pile on the board. 2. Pick up the top card from the stock pile or from one discard pile. Both actions are mandatory. Cards must be added in ascending sequence, but gaps are permitted. Investment cards may precede a numerical card, but may not be added afterward. Players need not embark on all 5 expeditions; only those that are embarked on by a player count toward that player's score. The game ends immediately when the last card is picked up from the stock pile. '''SCORING:''' For every expedition embarked on: 1. Take the sum of all numbered cards 2. Subtract 20 3. Multiply by (number of investment cards + 1) 4. Add 20 if the expedition contains 8 or more cards Final score = sum of all expeditions embarked on (whether positive or negative) ad24559618e4f50dd8880e12dc8d048508bb1c42 Rating 0 16 1739 1539 2016-01-09T03:13:29Z Jmike301 11097 wikitext text/x-wiki [[Category:Help]] == What is an Elo rating? == Your Elo rating for a game is an indicator of your level of skill at that game. It's a 4 digit number followed by the symbol http://fr.boardgamearena.com/theme/img/common/rank.png. Example: 1648 http://fr.boardgamearena.com/theme/img/common/rank.png. If you've never played a game on BGA, your initial rating will be 1500. Each time you win a game your rating increases, and it decreases each time you lose a game. == How many points do I gain / lose for each game? == The number of Elo points gained or lost in a game depends on (1) the Elo rating of your opponents, and (2) what place you achieve in the game (i.e. 1st place, 2nd place). For example: * If you end the game in a better position than a player with a higher Elo, you gain a lot of points. * If you end the game in a better position than a player with a lower Elo, you gain fewer points. * If you end the game in a worse position than a player with a lower Elo, you lose a lot of points. * And so on... == Some advice == * There's little to be gained by beating players with an Elo rating a lot lower than yours. Try to find opponents with a similar Elo rating to yourself: it's both more fun and better for your Elo. * What place you achieve in a game is very important when calculating the Elo. This is why it is important to continue fighting for minor places in the game even if you think you can't win. * The number of Elo points you can gain/lose during a game increases with the number of players. The maximum is reached when there is the "recommended number of players". Try to play games with this recommended number of players. * When you are the first player to quit a game in progress, you lose as many points as if you had finished the game in last place, plus an additional penalty of 10 points. Even if you are in a difficult situation it is in your interest to play the game until the end - or concede the victory to your opponent. == How is my Elo rating computed? == The BGA Elo system is directly based on the standard [http://en.wikipedia.org/wiki/Elo_rating_system Elo rating system] in use for chess. The Elo system's main principle is the following: the Elo points difference between 2 players determines the probability of each of them winning an encounter. If two players have the same Elo, they have an equal (50/50) probability of winning. If one player has 400 more points than the other, his probability of winning is 90%. Elo points gains and losses will, over time, tend to adjust the Elo rating of each player to reflect the actual probability that either of them will win a particular encounter. Some changes have been made to the Elo system used on BGA: * During your first 30 games, your Elo rating is more "elastic": you can win (or lose) more points in each game. This way, your Elo rating converges faster to you "natural" rating. * The original Elo rating system was designed for 2 player games. For games with more than 2 players, BGA considers (for the Elo rating) that you win a 2-player game against each opponent who placed below you, and that you lose a 2-player game against each who place above you. * Games with more than 2 players last longer. For this reason, there are more points to win (or lose) in such games... as long as the number of players does not exceed the "advised number of players" for that game. == Okay, but I want to know the formula! == The formula is exactly the one used by the Elo rating system, with the following adjustments: * First of all, if someone leaves a game for any reason this game is not taken into account by the Elo rating system. * K=60 for the first 30 games, K=40 afterwards. * K is multiplied by (N/2) for N-player games. If N exceeds the "advised number of players" for this game, K is multiplied by (A/2), where A is the "advised number of players". == Beginners, Average players, Good players, Experts, Masters == * Beginner: Everyone starts as a Beginner. You stay a Beginner until you achieve a victory, regardless of your Elo. If you have at least 1 victory, the following levels apply, depending on your Elo: * Average: < 1600 * Good: >= 1600 * Expert: >= 1800 * Master: >= 2000 25cd41e4dc3559d3c21e43a5144a42766742bb37 Gamehelpthroughtheages 0 168 1741 1598 2016-01-10T02:43:14Z Cokolada 11050 In the "Simple" and "Advanced" versions, the game ends immediately when there are no more cards to replenish the deck. wikitext text/x-wiki During your turn, you may spend your '''actions points''' to: * pick cards from the card rows (if you have room in your hand) ** Wonders cost an addition civil action for each wonder you have finished * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * build/upgrade military units '''Yellow counters''' represent your population. They can be in one of three places: * on the cards on your tableau * on your available worker pool * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in three places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce food or resources * on your wonder, marking how far along it's construction is Building up your civilisation: * '''Food''' lets you move workers from your yellow bank to your available worker pool. * '''Resources''' let you move workers from your available worker pool to a card on your tableau. * '''Science''' (light bulbs) lets you move cards from your hand to your tableau. * When your population grows, you will need to produce more '''happiness''' or your workers will stop working. * Producing '''culture''' will earn you victory points. * Producing more '''military strength''' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars In the "Simple" and "Advanced" versions, the game ends immediately when there are no more cards to replenish the deck. In the Advanced and Complete games, '''additional points are scored at the end of the game''' according to special event cards. But at the end of the Simple game, additional points are scored the same way every game: * 2 culture scored per 1 Strength (military) * 2 culture scored per Happy Face * 2 culture scored per level 1 technology in play * 1 culture scored per food or resource production per turn * 1 culture scored per 1 Science Rating (science gained per turn) 6b1db0d32db66dfdd2b0edf9c8060fada7548a12 1742 1741 2016-01-10T02:48:11Z Cokolada 11050 In the "Simple" and "Advanced" versions, the game ends immediately when there are no more cards to replenish the deck. wikitext text/x-wiki During your turn, you may spend your '''actions points''' to: * pick cards from the card rows (if you have room in your hand) ** Wonders cost an addition civil action for each wonder you have finished * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * build/upgrade military units '''Yellow counters''' represent your population. They can be in one of three places: * on the cards on your tableau * on your available worker pool * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in three places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce food or resources * on your wonder, marking how far along it's construction is Building up your civilisation: * '''Food''' lets you move workers from your yellow bank to your available worker pool. * '''Resources''' let you move workers from your available worker pool to a card on your tableau. * '''Science''' (light bulbs) lets you move cards from your hand to your tableau. * When your population grows, you will need to produce more '''happiness''' or your workers will stop working. * Producing '''culture''' will earn you victory points. * Producing more '''military strength''' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars In the "Simple" and "Advanced" versions, the game ends immediately when there are no more cards to replenish the deck as long as both players have played an equal number of turns. In the Advanced and Complete games, '''additional points are scored at the end of the game''' according to special event cards. But at the end of the Simple game, additional points are scored the same way every game: * 2 culture scored per 1 Strength (military) * 2 culture scored per Happy Face * 2 culture scored per level 1 technology in play * 1 culture scored per food or resource production per turn * 1 culture scored per 1 Science Rating (science gained per turn) a693d765b77b11f857dc56f3c1abeea3de4701c4 1743 1742 2016-01-10T02:48:34Z Cokolada 11050 wikitext text/x-wiki During your turn, you may spend your '''actions points''' to: * pick cards from the card rows (if you have room in your hand) ** Wonders cost an addition civil action for each wonder you have finished * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * build/upgrade military units '''Yellow counters''' represent your population. They can be in one of three places: * on the cards on your tableau * on your available worker pool * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in three places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce food or resources * on your wonder, marking how far along it's construction is Building up your civilisation: * '''Food''' lets you move workers from your yellow bank to your available worker pool. * '''Resources''' let you move workers from your available worker pool to a card on your tableau. * '''Science''' (light bulbs) lets you move cards from your hand to your tableau. * When your population grows, you will need to produce more '''happiness''' or your workers will stop working. * Producing '''culture''' will earn you victory points. * Producing more '''military strength''' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars In the "Simple" and "Advanced" versions, the game ends immediately when there are no more cards to replenish the deck and both players have played an equal number of turns. In the Advanced and Complete games, '''additional points are scored at the end of the game''' according to special event cards. But at the end of the Simple game, additional points are scored the same way every game: * 2 culture scored per 1 Strength (military) * 2 culture scored per Happy Face * 2 culture scored per level 1 technology in play * 1 culture scored per food or resource production per turn * 1 culture scored per 1 Science Rating (science gained per turn) 12947f16a63a32b299c97beb33d0ff789ec10742 1744 1743 2016-01-10T02:49:10Z Cokolada 11050 wikitext text/x-wiki During your turn, you may spend your '''actions points''' to: * pick cards from the card rows (if you have room in your hand) ** Wonders cost an addition civil action for each wonder you have finished * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * build/upgrade military units '''Yellow counters''' represent your population. They can be in one of three places: * on the cards on your tableau * on your available worker pool * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in three places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce food or resources * on your wonder, marking how far along it's construction is Building up your civilisation: * '''Food''' lets you move workers from your yellow bank to your available worker pool. * '''Resources''' let you move workers from your available worker pool to a card on your tableau. * '''Science''' (light bulbs) lets you move cards from your hand to your tableau. * When your population grows, you will need to produce more '''happiness''' or your workers will stop working. * Producing '''culture''' will earn you victory points. * Producing more '''military strength''' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars In the ''Simple'' and ''Advanced'' versions, the game ends immediately when there are no more cards to replenish the deck and both players have played an equal number of turns. In the Advanced and Complete games, '''additional points are scored at the end of the game''' according to special event cards. But at the end of the Simple game, additional points are scored the same way every game: * 2 culture scored per 1 Strength (military) * 2 culture scored per Happy Face * 2 culture scored per level 1 technology in play * 1 culture scored per food or resource production per turn * 1 culture scored per 1 Science Rating (science gained per turn) d8a89c7d6177731e3f2f64f916c4eeb18f744cd1 Grade 0 30 1745 1670 2016-01-13T08:25:13Z Deebster 11157 Undo revision 1614 by [[Special:Contributions/Sayth|Sayth]] ([[User talk:Sayth|talk]]) wikitext text/x-wiki Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. == All grades == * '''Mortal''': this is your grade when you just registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). Don't worry! You'll be an Angel soon! * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraphim can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherubim check that Seraphim are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. * '''Demon''': due to a major terms of use violation, this player is not allowed to do most of the things on the website during a period of time (or forever ......) :( 13bbf79601133265f9fdd262c7012c904205ab33 1746 1745 2016-01-13T08:25:54Z Deebster 11157 Undo revision 1613 by [[Special:Contributions/Sayth|Sayth]] ([[User talk:Sayth|talk]]) wikitext text/x-wiki Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a mortal. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the angel grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to devilkin or demon. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. == All grades == * '''Mortal''': this is your grade when you just registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). Don't worry! You'll be an Angel soon! * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraphim can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherubim check that Seraphim are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. * '''Demon''': due to a major terms of use violation, this player is not allowed to do most of the things on the website during a period of time (or forever ......) c30254932cdbd8e9af27cb324b4c8aaf2f538f12 Gamehelpflorenzacardgame 0 197 1747 1578 2016-01-13T10:33:02Z Maxibon 11158 wikitext text/x-wiki '''Il turno di gioco si divide in 4 fasi:''' * Pesca degli Artisti e dei Monumenti * Pesca delle carte Florenza * Azioni (4 per round più eventuali azioni extra ottenute dalle carte giocate) **Giocare una carta Florenza **Realizzare un Monumento **Riservarsi un Monumento o un Artista **Attivare una carta centrale (raccogli/vendi le risorse indicate da una carta che sia sul tavolo a faccia in su) **Mandare fuori un lavoratore a giornata (raccogli 50 Fiorini) **Andare al Mercato (vendi/compra/scambia risorse con la riserva) **Cercare ispirazione (pesca una carta Florenza extra) * Operazioni di Fine turno **Scartare tutte le carte Monumento rimaste sul tavolo, tranne le due più a sinistra **Scartare tutte le carte Artista rimaste eventualmente in gioco **Scartare tutte le carte Florenza in mano ai giocatori, tranne una a scelta del giocatore **Distribuire le rendite **Eleggere il nuovo Capitano del Popolo **Ripristinare le carte centrali '''Fine della partita''' dopo 5 turni. 125519f6af622539c8f3ac6121125400972b3d62 Getting started 0 10 1748 1484 2016-01-15T06:53:47Z Red moon 2496 wikitext text/x-wiki [[Category:Help]] With '''Board Game Arena''' you can play within a few clicks. By choosing "[http://en.boardgamearena.com/#!lobby Play now]" on the top menu, you get a list of game tables waiting for players. You should select the games you want to play now to make them appear at the top of the page. You can join a game by clicking on a table, then click on "Join game". If you prefer, you can create a new game table: click on the green play button that corresponds to the game you want to play, and wait for your opponents. Important to know before you start: * It's much better to join a table already created than to create a new one. * For most popular games you will find opponents at any time. For the others, try to connect around peak hour (around 22h CEST) to maximize your chances. * When you start a game you can't leave the table until it ends. If you leave you will receive a penalty which will create difficulties finding opponents later. 513b39240a26793f18ec63be2e6ec69c32a101af Browser support 0 13 1749 969 2016-01-15T07:25:06Z Red moon 2496 wikitext text/x-wiki <h3>For the best experience, we recommend:</h3> * '''Google Chrome 10+''' [http://www.google.com/chrome Windows] [http://www.google.com/chrome?platform=mac Mac] [http://www.google.com/chrome?platform=linux Linux] * '''Mozilla Firefox 4+''' [http://www.mozilla.org/products/firefox/ Windows] [http://www.mozilla.org/products/firefox/ Mac] [http://www.mozilla.org/products/firefox/ Linux] Board Game Arena takes advantage of the most recent web technology to make it possible for you to play without installing anything on your computer: no software to download or update, no plugins to install, etc. Consequently, to play you need to use a modern web browser. Generally speaking, the more recent your web browser is, the more pleasant your game experience on Board Game Arena will be. This website makes intensive use of Javascript and your browser's graphics capabilities. Thus, if you want to have the best gaming experience with Board Game Arena, you should use one of the browsers listed above. However, we officially support the following browsers: * Google Chrome 4+ * Mozilla Firefox 3.5+ * Internet Explorer 9+ * Safari 4+ We also support playing on iPads or similar tablets,or mobile phones.) [[Category:Help]] fba186eef7f33086a8066a79b348e2404404fb23 Moderation and grades 0 14 1750 1507 2016-01-15T08:03:38Z Red moon 2496 wikitext text/x-wiki Board Game Arena是一個友好且相互尊重的玩家社區。審核與等級系統幫助我們確保少數不能尊重本網站的玩家不會干擾到別的玩家。 當你在Board Game Arena註冊時,你得到'''凡人'''的​​等級。你可以使用本網站的大多數功能,但不能使用部分功能(比如在公眾頻道上發言)。 過了一段時間,你都提升到了'''天使'''等級。有了這個級別,你可以使用本網站的全部功能。但是,如果你違規,你可以被降級為'''惡魔'''或'''路西法'''。 == 版主 == 版主(Moderation) 在 BGA 以BGA社區為基礎,義務地處理檢舉,並作出裁決。 你可以到[[http://boardgamearena.com/#!team BGA team]] 頁面查看管理人員名單。 一般情況下,每宗檢舉所需處理時間十份短,但有時處理途中會遇到困難,並需要作出額外調查。但不用擔心,我們會處理每宗檢舉。 == 等級列表 == &'''凡人''':剛申請帳號時你所處的等級,你能夠使用大部分的功能(除了使用公眾頻道) & '''天使''':這是一個標準的玩家等級,要取得這個等級你需要登錄滿3日、完成3場比賽以及3個正面的評價 & '''熾天使''':這是一個版主的等級,熾天使能夠懲罰不遵守BGA條款的玩家(如沒有禮貌, 卑劣行為) & '''智天使'':這是一個超級版主的等級,智天使能夠檢查熾天使的裁決是否公正 & '''大天使'''"這是BGA管理者的等級 & '''惡魔''':由於違犯了BGA條款而降為惡魔的玩家。他們不允許去使用這個網站的功能一段時間(或者永久....) & '''路西法''':由於違犯了BGA重要條款而降生為路西法的玩家。他們不允許在網站中發言(或發表討論)一段時間 cd7c4f3120606bf13025c674ad226c236a2b24e4 1751 1750 2016-01-15T08:03:56Z Red moon 2496 /* 版主 */ wikitext text/x-wiki Board Game Arena是一個友好且相互尊重的玩家社區。審核與等級系統幫助我們確保少數不能尊重本網站的玩家不會干擾到別的玩家。 當你在Board Game Arena註冊時,你得到'''凡人'''的​​等級。你可以使用本網站的大多數功能,但不能使用部分功能(比如在公眾頻道上發言)。 過了一段時間,你都提升到了'''天使'''等級。有了這個級別,你可以使用本網站的全部功能。但是,如果你違規,你可以被降級為'''惡魔'''或'''路西法'''。 == 版主 == 版主(Moderation) 在 BGA 以BGA社區為基礎,義務地處理檢舉,並作出裁決。 你可以到[http://boardgamearena.com/#!team BGA team] 頁面查看管理人員名單。 一般情況下,每宗檢舉所需處理時間十份短,但有時處理途中會遇到困難,並需要作出額外調查。但不用擔心,我們會處理每宗檢舉。 == 等級列表 == &'''凡人''':剛申請帳號時你所處的等級,你能夠使用大部分的功能(除了使用公眾頻道) & '''天使''':這是一個標準的玩家等級,要取得這個等級你需要登錄滿3日、完成3場比賽以及3個正面的評價 & '''熾天使''':這是一個版主的等級,熾天使能夠懲罰不遵守BGA條款的玩家(如沒有禮貌, 卑劣行為) & '''智天使'':這是一個超級版主的等級,智天使能夠檢查熾天使的裁決是否公正 & '''大天使'''"這是BGA管理者的等級 & '''惡魔''':由於違犯了BGA條款而降為惡魔的玩家。他們不允許去使用這個網站的功能一段時間(或者永久....) & '''路西法''':由於違犯了BGA重要條款而降生為路西法的玩家。他們不允許在網站中發言(或發表討論)一段時間 ff114578b032c1a8917e432fbda01b20808294ab Moderation and grades 0 14 1752 1751 2016-01-15T08:04:32Z Red moon 2496 wikitext text/x-wiki [[Category:Help]] Board Game Arena is a friendly and respectful community of players. The moderation and grades system help us to ensure that the minority of players who disrespect the spirit of this website can't bother other players. When you register on Board Game Arena, you're a '''mortal'''. You can access most of the functionalities of this website, except some of them (ex: speaking on global chat). After a while, you are promoted to the '''angel''' grade. With this grade you are able to access all functionalities of the service. But, if you go against the Board Game Arena terms, you can be moderated and demoted to '''devilkin''' or '''demon'''. If you manage to become a well appreciated player, you can become a moderator with a superior grade: seraph or cherub. == Moderation == Moderation on BGA is community based. A group of volunteers process the reports, and decide which action to do (ex: exclude player for X days). BGA Moderators made a difficult work that is absolutely needed to have a nice community. You can see who they are from the [[http://boardgamearena.com/#!team BGA team]] page. Usually reports are processed quite fast, but sometimes this is not easy and there are some additional checks to perform. But don't be afraid: we review every report. == All grades == * '''Mortal''': this is your grade when you registered on Board Game Arena. You can access almost all functionalities of the website (but you can't speak on general channel). * '''Angel''': this is the grade of regular players. To be promoted to this grade, you need: 3 days seniority, 3 games played and 3 positive reputation points. * '''Seraph''': this is the moderator grade. Seraph can punish players who disrespect BGA terms of use: reputation penalties, inferior grade. * '''Cherub''': this is the super moderator grade. Cherub check that Seraph are fair and unbiased. * '''Archangel''': this is the Board Game Arena administrators' grade. * '''Demon''': due to a major terms of use violation, this player is not allowed to do anything on the website during a period of time (or forever ...) * '''Devilkin''': due to a terms of use violation, this player is not allowed to speak on Board Game Arena (or publish anything) during a period of time. f62030b7670469b182c571cf9a70b455c5aa5725 Tutorial reversi 0 57 1753 1643 2016-01-16T04:09:19Z Skyfire815 11096 /* The discs */ wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for white and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('img/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slidetoObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just add "this.addTokenOnBoard( 2, 2, [player_id] )" in the "setup" Javascript method in reversi.js, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "states.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where she is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where she is allowed to play. This method will be used in particular: * As we just said, to help the player to see where she can play. * When the player plays, to check if she has the right to play here. This is pure PHP programming here, and there are no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight the squares where the player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on the server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in stats.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". f870b98b8fb97553df8f4ae645a6c3c9aa9cff38 Game clock 0 15 1754 1587 2016-01-22T00:55:19Z Hypersoar 8116 /* Game clock system philosophy */ wikitext text/x-wiki [[Category:Help]] On '''Board Game Arena''' you are playing "live" (real time) or "turn-based" (asynchronously). In both cases, you have an allotted delay to play your moves. Most of the time, your initial delay at the beginning of a game is some minutes (in realtime mode) or some days (in turn-based mode). During each turn, or on specific occasions, you get an additional delay. If you have no more time to play, you will get a "clock" penalty and your opponents can decide to skip your turns (and consequently make you loose the game). == Game clock system philosophy == The game clock has been designed with the following principles: * Even if you are in a losing position, it is always more interesting (for your ELO and your reputation) to play the game until the end. * Make sure that if your opponent left the game (or has been disconnected), it won't take long before you can expel him and win the game by forfeit. * Expelling an opponent is always a volunteer action, so you can agree with your opponent to forget the time limit if you want to. * If your opponent does not play and run out of time, this is always more interesting for you to try to make him back into the game than to punish him with penalties or skipping turn. In anyway, don't forget that respecting your allotted time is VERY important. == Time to think == Your allotted time to think is displayed on the right of your player's name. When it's your turn to play, this time is also displayed at the top of the web page. == Game speed == Table administrator can make a choice between some game speed profile (example: fast, normal, slow). There are many speeds for each mode (realtime and turn-based). The additional amount of time credited each turn depends on the chosen game speed profile. Be careful to check the game speed setting before the game starts to adjust your timing. The interface displays an estimation of the game duration based on recently played games with the same speed settings. Note: your allotted time to think cannot get higher that your initial time to think. For example, if you start the game with 5 minutes of thinking time, you time will be limited to 5 minutes maximum. Note: playing without a time limit is strongly discouraged, except if you are playing with friends, or to discover a new game. Remember that without time limit, you can't skip the turn of a player that is not playing. == Running out of time == As soon as you run out of time (negative clock), you get a clock penalty. When a player has a negative clock, any one of his opponents can make him skip his turn. Once this has been done, all following turns are skipped automatically. After player A's turn has been "skipped" at y% of game progression, the game results are "neutralized". It means that: * Player A is going to loose the game anyway (last position), with the corresponding ELO loss. * In addition, Player A will get a "leave" penalty on his profile and an additional -10 ELO points penalty. * Player A's opponents are going to win the game anyway (all tied at the first position), with y% of the ELO points they would have normally won. This is impossible to lose points when your opponent left the game. Example: player "Albert" left a 2 players game at 50% of the game progression. His opponent "Ben" skips his turn. At the end of the game, "Albert" will get -30 ELO points (normal loss for a game loss) plus an additional -10 ELO points (penalty for leaving), plus a red "leave" penalty on his reputation profile. "Ben" is going to win 15 ELO points (50% of the normal 30 ELO points win). Note: you can't skip the turn of an opponent if your own clock is even more negative than him. For example, if "Ben"'s clock is -3:45 and "Albert"'s clock is "-0:05", Albert can expel Ben but Ben cannot expel Albert. == Continue the game after a "skip turn" == If you are playing in a game where a player skips all his turns, you may continue the game if you like, or not. This has no effect on anything (game results, penalties, and so on...). This is "just for fun". == "My opponent is too slow" == Each of us has different expectations on game speed. Please remember that as soon as a table has been set up at a given game speed, each player is allowed to use all his allotted time to think. If you want to play fast, set up or join only tables with "fast" mode on, but don't bully an opponent to play when he has the right to use his alloted time to think. == "I would like to think a little" == If you are in a critical step of the game and want to take some time to think, you can click on the "I would like to think a little" link at the top right of the page. Thus, your opponents will get a message and won't be thinking that you are away from keyboard or disconnected. Clicking on this link is not mandatory, but we encourage its use as a courtesy. 81a629909d71ee93a12271dbcbce77e6c1f42aec Gamehelpcoloretto 0 33 1755 1166 2016-01-23T22:52:16Z Elisha 2997 Simple text and spacing fixes wikitext text/x-wiki There are several colors of chameleons (depending on the number of players) and 2 kinds of special cards: Joker and +2. At the beginning each players gets randomly 1 card with a chameleon of different color than any other player. On their turn players can : 1. draw a new card and put it in one of the rows (there are as many rows as players) 2. take a row of cards When a player takes a row his or her turn is skipped until all players have taken a row. Then a new round starts, and players can again fill rows with cards. The game ends at the end of a round during which the 'Last round' card is drawn. The player who drew the 'Last round' card puts it away and draws another card. Same colored chameleons are put into sets. The more cards of that color you have the more points it is worth. Only 3 sets bring you positive points, while every other set brings you negative points. You get to choose at the end of the game which sets will be positive (the BGA does that for you). The Joker (chameleon with many-colored background) can be put into any set at the end of the game. The +2 card always brings you 2 positive points at the end of the game. It is never a part of a set. The player with the most points wins. 24338f23af79cab924f6e1eed1e589e5530479c4 Gamehelpk2 0 184 1756 1411 2016-01-26T12:50:01Z Gawainno 11318 wikitext text/x-wiki '''Turn Summary''' <ol> <li>'''Card Selection'''</li> <ol> <li>Each player plays 3 cards face down.</li> <li>Players reveal them simultaneously.</li> </ol> <li>'''Risk Tokens'''</li> <ol> <li>The player with the most movement points takes a risk token. In case of a tie, no one takes a risk token.</li> <li>Another risk token is revealed if needed.</li> </ol> <li>'''Action Phase'''</li> <ol> <li>Players move their climbers using their played (green) cards.</li> <li>Placing a tent costs the same as the cost to enter that space.</li> <li>Players increase their climbers' acclimatization level using their played (blue) cards.</li> <li>The player with a risk token must suffer the consequences and either reduce their movement by that amount or, if they choose not to, subtract acclimatization points from a climber who had one or more cards assigned to this turn.</li> <li>Each climber's newly gained victory points are marked on the victory point track.</li> <li>Note the influence of weather on movement (only in winter weather)!.</li> </ol> <li>'''Acclimatization Checks'''</li> <ol> <li>Add/subtract acclimatization according to each climber's current space.</li> <li>A tent of the player's color adds +1 to acclimatization.</li> <li>Subtract acclimatization resulting from the current weather, if in the affected altitude zone.</li> <li>If acclimatization exceeds 6, it is reduced back to 6.</li> <li>If acclimatization drops below 1, the climber dies, losing any VP gained.</li> </ol> <li>'''End of Turn'''</li> <ol> <li>The starting player marker passes to the left.</li> <li>The weather marker moves to the next space.</li> <li>Draw 3 cards to have 6 again.</li> </ol> </ol> ff522351e4b1674a2e84716771c2e8b212370431 Gamehelpdarkagent 0 207 1757 1731 2016-01-29T16:37:36Z Philcollins 10686 /* Pitch of DARK AGENT board game : */ wikitext text/x-wiki == Goal and Context of DARK AGENT board game : == At the head of a secret service, you use your spy satellites (tokens of your color) to coordinate attacks on targets that you designate to your agents : - Objectives (tiger), Sentinel (gray), enemies Agents (their color), or the Dark Agent (black) you win all their victory points when capturing them and place them in front of you; - Equipment (object in a white disk), single use, are taken over to be used and discarded later; - Special actions (red with no points) Are resolved immediately and remain in place. One or more of your agents can attack a target only if your satellites lets you see both your agents and the target. When players have had them all, the number of captured target agreed early in the game (2 to 5 on the 5 available), it ends. You can add the capture of the Dark Agent as a further condition endgame. The player accumulating the most points wins. He adds the points of his agents still on the ground. Also note that each time a player wins an aim, he takes the bonus 3 PV token to its previous owner. Unplayed nations are used as neutral nations. == Equipment cards effects == Adrenaline : Boost an agent with a bonus equal to his basic level -------- Binoculars : add two markers 'attempts' on an aim, then it's easier to attack it ---- Bulletproof jacket : Gives you invulnerability till a missed attack. Must be used before attack with at least a spy selected. Can be used for Defense, after dice result in case one of your spy is attacked (then Discarded). ---- Explosives : Allow to attack protected aims (with sentinel or enemy spy around) ---- Jet-pack : You can exchange place of one of your spy with the place of an opponent spy or a sentinel. ---- Rifle : Add +2 to all your attack, and allow you to attack one sentinel (spotted or not), wherever on the TDO (theater of operations). Allow you to re-attack a sentinel by this way. ---- Rocket launcher : Use before attack, allow to change a dice on each attack (to get a six for example). One spy must be selected before using this equipment ---- Rubber dinghy (boat) : Use this equipment to send a spy on the TDO, you must have an free square available on the TDO to do this (where the spy will land) ---- Sat-laptop : This Laptop will allow you to use a satellite from other players to spot a new square on the TDO. Cannot be used for neutral sat, except in 1-player game. Cannot be used twice the same row in the same turn. == Permanent power of Aims == Prisoner : Once by turn, exchange place of one of your spy with an enemy (dark agent, opponent spy or sentinel) ---- Scientist : All of your spies get invulnerability ---- Nuclear deterrence : All your attacks get +2 bonus ---- Control Center : All your satellites are supers-satellites ---- Briefcase : One more vote FOR if you vote FOR the peace == Game tactics : == This game is rich of tactical and strategic possibilities. Players can take the game in hand before the first three plays. It has many strenghs : - Game duration could be calibrated (2 players / aim, the game lasts less than 10 minutes). - Play turns are smooth, even with 6 players (calibrated in duration with the number of aims to win in order to make a short/long play) - The single player mode is a real challenge and allows to understand the mechanisms. - There are many strategies and many ways to win. == Tutorials == Youtube tutorials are available : search spacereindeers, or go to [http://www.spacereindeers.com/dark-agent link DarkAgent] 2c2fc7fb462ba29a84478001793555ed96809fbd Gamehelpkoikoi 0 211 1758 2016-02-01T14:44:58Z Een 3 Created page with "== About yaku (card combinations) == You can use the '''in game help icon''' to display a popup listing all the possible yaku and how many points they are worth. All the ya..." wikitext text/x-wiki == About yaku (card combinations) == You can use the '''in game help icon''' to display a popup listing all the possible yaku and how many points they are worth. All the yaku are '''combinative''', except the "Bright" cards yaku, which are exclusive (you will always score the biggest available). == About multipliers == As is often the case with traditional games, there is a lot of variants for playing Koi-koi, especially in regards to scoring. For Board Game Arena, two variants are provided through the options when creating the game: * Soft "Koi!" is a variant adapted from [http://www.sloperama.com/hanafuda/rules.html the Sloperama site rules] which is all about saying "Koi!". Of course you run the risk of your opponent making a yaku and scoring for the month (round) before you can score yourself, but in exchange for that risk, you get '''a multiplier''' so that if you manage to increase your score with another yaku, you will score a lot more. Also, a starting multiplier will be set for the month if some "Bright cards" have been drawn for the field when dealing for the month. So this is an aggressive variant with a lot of points available if you push your luck. * Hard "Koi:" is a variant adapted from [https://web.archive.org/web/20120421175954/http://hanafubuki.org/koikoi.html the Hanafubuki site rules] which is less incitative to call "Koi!" since you won't get a multiplier just for saying "Koi!". Instead, '''your opponent''' will! If you say "Koi!" at least once, then if your opponent manages to score his score will be doubled. Still, at some point you'll risk it, because if you manage to improve your yaku to score 7 points or more, then '''your score''' will be doubled. 05a01502b6e76d0b831c70c5e9da999e546b4a4a 1759 1758 2016-02-01T17:15:54Z Een 3 wikitext text/x-wiki == About yaku (card combinations) == You can use the '''in game help icon''' to display a popup listing all the possible yaku and how many points they are worth. All the yaku are '''combinative''', except the "Bright" cards yaku, which are exclusive (you will always score the biggest available). == About multipliers == As is often the case with traditional games, there is a lot of variants for playing Koi-koi, especially in regards to scoring. For Board Game Arena, two variants are provided through the options when creating the game: * Soft "Koi!" is a variant adapted from [http://www.sloperama.com/hanafuda/rules.html the Sloperama site rules] which is all about saying "Koi!". Of course you run the risk of your opponent making a yaku and scoring for the month (round) before you can score yourself, but in exchange for that risk, each time you will get '''a multiplier''' so that if you manage to increase your score with another yaku, you will score a lot more. Also, a starting multiplier will be set for the month if some "Bright cards" have been drawn for the field when dealing for the month. So this is an aggressive variant with a lot of points available if you push your luck. * Hard "Koi!" is a variant adapted from [https://web.archive.org/web/20120421175954/http://hanafubuki.org/koikoi.html the Hanafubuki site rules] which is less incitative to call "Koi!" since you won't get a multiplier just for saying "Koi!". Instead, '''your opponent''' will! If you say "Koi!" at least once, then if your opponent manages to score his score will be doubled. Still, at some point you'll risk it, because if you manage to improve your yaku to score 7 points or more, then '''your score''' will be doubled. 1b86c8b8be3d94f52564e8b2f949074dec98b481 1760 1759 2016-02-01T17:21:10Z Een 3 wikitext text/x-wiki == About yaku (card combinations) == You can use the '''in game help icon''' to display a popup listing all the possible yaku and how many points they are worth. All the yaku are '''combinative''', except the "Bright" cards yaku, which are exclusive (you will always score the biggest available). == About multipliers == As is often the case with traditional games, there is a lot of variants for playing Koi-koi, especially in regards to scoring. For Board Game Arena, two variants are provided through the options when creating the game: * '''Soft "Koi!"''' is a variant adapted from [http://www.sloperama.com/hanafuda/rules.html the Sloperama site rules] which is all about saying "Koi!". Of course you run the risk of your opponent making a yaku and scoring for the month (round) before you can score yourself, but in exchange for that risk, each time you will get '''a multiplier''' so that if you manage to increase your score with another yaku, you will score a lot more. Also, a starting multiplier will be set for the month if some "Bright cards" have been drawn for the field when dealing for the month. So this is an aggressive variant with a lot of points available if you push your luck. * '''Hard "Koi!"''' is a variant adapted from [https://web.archive.org/web/20120421175954/http://hanafubuki.org/koikoi.html the Hanafubuki site rules] which is less incitative to call "Koi!" since you won't get a multiplier just for saying "Koi!". Instead, '''your opponent''' will! If you say "Koi!" at least once, then if your opponent manages to score his score will be doubled. Still, at some point you'll risk it, because if you manage to improve your yaku to score 7 points or more, then '''your score''' will be doubled. 9261bcf250b1862ec9bd5047f411cbc509f96828 1761 1760 2016-02-01T17:23:27Z Een 3 wikitext text/x-wiki == About yaku (card combinations) == You can use the '''in game help icon''' to display a popup listing all the possible yaku and how many points they are worth. All the yaku are '''combinative''', except the "Bright" cards yaku, which are exclusive (you will always score the biggest available). == About multipliers == As is often the case with traditional games, there is a lot of variants for playing Koi-koi, especially in regards to scoring. For Board Game Arena, two variants are provided through the options when creating the game: * - '''Soft "Koi!"''' is a variant adapted from [http://www.sloperama.com/hanafuda/rules.html the Sloperama site rules] which is all about saying "Koi!". Of course you run the risk of your opponent making a yaku and scoring for the month (round) before you can score yourself, but in exchange for that risk, each time you will get '''a multiplier''' so that if you manage to increase your score with another yaku, you will score a lot more. Also, a starting multiplier will be set for the month if some "Bright cards" have been drawn for the field when dealing for the month. So this is an aggressive variant with a lot of points available if you push your luck. * - '''Hard "Koi!"''' is a variant adapted from [https://web.archive.org/web/20120421175954/http://hanafubuki.org/koikoi.html the Hanafubuki site rules] which is less incitative to call "Koi!" since you won't get a multiplier just for saying "Koi!". Instead, '''your opponent''' will! If you say "Koi!" at least once, then if your opponent manages to score his score will be doubled. Still, at some point you'll risk it, because if you manage to improve your yaku to score 7 points or more, then '''your score''' will be doubled. 3223b3cef54f989ee21441069ab708275b81d20c 1764 1761 2016-02-04T08:58:19Z Een 3 Added variants wikitext text/x-wiki == About yaku (card combinations) == You can use the '''in game help icon''' to display a popup listing all the possible yaku and how many points they are worth. All the yaku are '''combinative''', except the "Bright" cards yaku, which are exclusive (you will always score the biggest available). == About multipliers == As is often the case with traditional games, there is a lot of variants for playing Koi-koi, especially in regards to scoring. For Board Game Arena, two variants are provided through the options when creating the game: * - '''Soft "Koi!"''' is a variant adapted from [http://www.sloperama.com/hanafuda/rules.html the Sloperama site rules] which is all about saying "Koi!". Of course you run the risk of your opponent making a yaku and scoring for the month (round) before you can score yourself, but in exchange for that risk, each time you will get '''a multiplier''' so that if you manage to increase your score with another yaku, you will score a lot more. Also, a starting multiplier will be set for the month if some "Bright cards" have been drawn for the field when dealing for the month. So this is an aggressive variant with a lot of points available if you push your luck. * - '''Hard "Koi!"''' is a variant adapted from [https://web.archive.org/web/20120421175954/http://hanafubuki.org/koikoi.html the Hanafubuki site rules] which is less incitative to call "Koi!" since you won't get a multiplier just for saying "Koi!". Instead, '''your opponent''' will! If you say "Koi!" at least once, then if your opponent manages to score his score will be doubled. Still, at some point you'll risk it, because if you manage to improve your yaku to score 7 points or more, then '''your score''' will be doubled. == A few variants == For the "Viewing the Moon" and "Viewing the Cherry Blossoms" : * - '''Standard''' : both yaku are available * - '''Rain ruins the party''' : if a player captures at least one card of November (rain), the party is ruined, both yaku are unavailable for this player * - '''No viewing yaku''' : both yaku are unavailable. For managing draws at the end of the month : * - '''No points awarded''' : no player gets any points in case of a draw * - '''Dealer`s privilege''' : the dealer (first player) gets 6 points in case of a draw. 0936932bc7ffa9001dee3d51bcb5aa98684d8ffe 1768 1764 2016-02-04T22:13:38Z Een 3 wikitext text/x-wiki == About yaku (card combinations) == You can use the '''in game help icon''' to display a popup listing all the possible yaku and how many points they are worth. All the yaku are '''combinative''', except the "Bright" cards yaku, which are exclusive (you will always score the biggest available). == About multipliers == As is often the case with traditional games, there is a lot of variants for playing Koi-koi, especially in regards to scoring. For Board Game Arena, two variants are provided through the options when creating the game: * - '''Soft "Koi!"''' is a variant adapted from [http://www.sloperama.com/hanafuda/rules.html the Sloperama site rules] which is all about saying "Koi!". Of course you run the risk of your opponent making a yaku and scoring for the month (round) before you can score yourself, but in exchange for that risk, each time you will get '''a multiplier''' so that if you manage to increase your score with another yaku, you will score a lot more. Also, a starting multiplier will be set for the month if some "Bright cards" have been drawn for the field when dealing for the month. So this is an aggressive variant with a lot of points available if you push your luck. * - '''Hard "Koi!"''' is a variant adapted from [https://web.archive.org/web/20120421175954/http://hanafubuki.org/koikoi.html the Hanafubuki site rules] which is less incitative to call "Koi!" since you won't get a multiplier just for saying "Koi!". Instead, '''your opponent''' will! If you say "Koi!" at least once, then if your opponent manages to score his score will be doubled. Still, at some point you'll risk it, because if you manage to improve your yaku to score 7 points or more, then '''your score''' will be doubled. Please also note that: * - if a month ends by lack of cards in hand and no player has managed to form a yaku, the dealer for the month (first player) gets 6 points ("dealer's privilege"); * - if a month ends by lack of cards in hand and at least a player managed to form a yaku (and said "Koi!" to continue), it's a draw and nobody gets any points. == About "Viewing" yaku == A few variants have been implementend for the "Viewing the Moon" and "Viewing the Cherry Blossoms" yaku: * - '''Standard''' : both yaku are available * - '''Rain ruins the party''' : if a player captures at least one card of November (rain), the party is ruined, both yaku are unavailable for this player * - '''No viewing yaku''' : both yaku are unavailable. 3bc654848e20f2d86540d6e79db01ee432989047 1769 1768 2016-02-04T22:15:19Z Een 3 wikitext text/x-wiki == About yaku (card combinations) == You can use the '''in game help icon''' to display a popup listing all the possible yaku and how many points they are worth. All the yaku are '''combinative''', except the "Bright" cards yaku, which are exclusive (you will always score the biggest available). == About multipliers == As is often the case with traditional games, there is a lot of variants for playing Koi-koi, especially in regards to scoring. For Board Game Arena, two variants are provided through the options when creating the game: * - '''Soft "Koi!"''' is a variant adapted from [http://www.sloperama.com/hanafuda/rules.html the Sloperama site rules] which is all about saying "Koi!". Of course you run the risk of your opponent making a yaku and scoring for the month (round) before you can score yourself, but in exchange for that risk, each time you will get '''a multiplier''' so that if you manage to increase your score with another yaku, you will score a lot more. Also, a starting multiplier will be set for the month if some "Bright cards" have been drawn for the field when dealing for the month. So this is an aggressive variant with a lot of points available if you push your luck. * - '''Hard "Koi!"''' is a variant adapted from [https://web.archive.org/web/20120421175954/http://hanafubuki.org/koikoi.html the Hanafubuki site rules] which is less incitative to call "Koi!" since you won't get a multiplier just for saying "Koi!". Instead, '''your opponent''' will! If you say "Koi!" at least once, then if your opponent manages to score his score will be doubled. Still, at some point you'll risk it, because if you manage to improve your yaku to score 7 points or more, then '''your score''' will be doubled. Please also note how draws are handled: * - if a month ends by lack of cards in hand and no player has managed to form a yaku, the dealer for the month (first player) gets 6 points ('''"dealer's privilege"'''); * - if a month ends by lack of cards in hand and at least a player managed to form a yaku (and said "Koi!" to continue), it's a draw and nobody gets any points. == About "Viewing" yaku == A few variants have been implementend for the "Viewing the Moon" and "Viewing the Cherry Blossoms" yaku: * - '''Standard''' : both yaku are available * - '''Rain ruins the party''' : if a player captures at least one card of November (rain), the party is ruined, both yaku are unavailable for this player * - '''No viewing yaku''' : both yaku are unavailable. c834334f6108259fe497356dcc8c907fb6a19015 1770 1769 2016-02-14T17:23:39Z Een 3 wikitext text/x-wiki == About yaku (card combinations) == You can use the '''in game help icon''' to display a popup listing all the possible yaku and how many points they are worth. All the yaku are '''combinative''', except the "Bright" cards yaku, which are exclusive (you will always score the biggest available). == About multipliers == As is often the case with traditional games, there is a lot of variants for playing Koi-koi, especially in regards to scoring. For Board Game Arena, two variants are provided through the options when creating the game: * - '''Soft "Koi!"''' is a variant adapted from [http://www.sloperama.com/hanafuda/rules.html the Sloperama site rules] which is all about saying "Koi!". Of course you run the risk of your opponent making a yaku and scoring for the month (round) before you can score yourself, but in exchange for that risk, each time you will get '''a multiplier''' so that if you manage to increase your score with another yaku, you will score a lot more. Also, a starting multiplier will be set for the month if some "Bright cards" have been drawn for the field when dealing for the month. So this is an aggressive variant with a lot of points available if you push your luck. * - '''Hard "Koi!"''' is a variant adapted from [https://web.archive.org/web/20120421175954/http://hanafubuki.org/koikoi.html the Hanafubuki site rules] which is less incitative to call "Koi!" since you won't get a multiplier just for saying "Koi!". Instead, '''your opponent''' will! If you say "Koi!" at least once, then if your opponent manages to score his score will be doubled. Still, at some point you'll risk it, because if you manage to improve your yaku to score 7 points or more, then '''your score''' will be doubled. Please also note how draws are handled: * - if a month ends by lack of cards in hand and no player has managed to form a yaku, the dealer for the month (first player) gets 6 points ('''"dealer's privilege"'''); * - if a month ends by lack of cards in hand and at least a player managed to form a yaku (and said "Koi!" to continue), it's a draw and nobody gets any points. == About "Viewing" yaku == A few variants have been implementend for the "Viewing the Moon" and "Viewing the Cherry Blossoms" yaku: * - '''Viewing yaku enabled''' : both yaku are available * - '''Rain ruins the party''' : if a player captures at least one card of November (rain), the party is ruined, both yaku are unavailable for this player * - '''Viewing yaku disabled''' : both yaku are unavailable. 787a09d737d30065bb57b7e5fe1373b5cf2e0dbf 1771 1770 2016-02-14T17:45:24Z Een 3 First to play variant wikitext text/x-wiki == About yaku (card combinations) == You can use the '''in game help icon''' to display a popup listing all the possible yaku and how many points they are worth. All the yaku are '''combinative''', except the "Bright" cards yaku, which are exclusive (you will always score the biggest available). == About multipliers == As is often the case with traditional games, there is a lot of variants for playing Koi-koi, especially in regards to scoring. For Board Game Arena, two variants are provided through the options when creating the game: * - '''Soft "Koi!"''' is a variant adapted from [http://www.sloperama.com/hanafuda/rules.html the Sloperama site rules] which is all about saying "Koi!". Of course you run the risk of your opponent making a yaku and scoring for the month (round) before you can score yourself, but in exchange for that risk, each time you will get '''a multiplier''' so that if you manage to increase your score with another yaku, you will score a lot more. Also, a starting multiplier will be set for the month if some "Bright cards" have been drawn for the field when dealing for the month. So this is an aggressive variant with a lot of points available if you push your luck. * - '''Hard "Koi!"''' is a variant adapted from [https://web.archive.org/web/20120421175954/http://hanafubuki.org/koikoi.html the Hanafubuki site rules] which is less incitative to call "Koi!" since you won't get a multiplier just for saying "Koi!". Instead, '''your opponent''' will! If you say "Koi!" at least once, then if your opponent manages to score his score will be doubled. Still, at some point you'll risk it, because if you manage to improve your yaku to score 7 points or more, then '''your score''' will be doubled. Please also note how draws are handled: * - if a month ends by lack of cards in hand and no player has managed to form a yaku, the dealer for the month (first player) gets 6 points ('''"dealer's privilege"'''); * - if a month ends by lack of cards in hand and at least a player managed to form a yaku (and said "Koi!" to continue), it's a draw and nobody gets any points. == About "Viewing" yaku == A few variants have been implementend for the "Viewing the Moon" and "Viewing the Cherry Blossoms" yaku: * - '''Viewing yaku enabled''' : both yaku are available (this is the default) * - '''Rain ruins the party''' : if a player captures at least one card of November (rain), the party is ruined, both yaku are unavailable for this player * - '''Viewing yaku disabled''' : both yaku are unavailable. == About "First play" == Getting the first play (and thus being the first to choose from the field) is a nice advantage. Some variants have been added upon request: * - '''Winner starts the next month''' : the winner for the current month gets to play first the next month (this is the default) * - '''Loser starts the next month''' : the player who lost this month gets to play first the next month * - '''Alternate starting player''' : the player who didn't get to play first this month will play first the following month. e31c69f1e45ef184f79349bdd813472df0b2b165 1772 1771 2016-02-14T17:46:00Z Een 3 /* About "First play" */ wikitext text/x-wiki == About yaku (card combinations) == You can use the '''in game help icon''' to display a popup listing all the possible yaku and how many points they are worth. All the yaku are '''combinative''', except the "Bright" cards yaku, which are exclusive (you will always score the biggest available). == About multipliers == As is often the case with traditional games, there is a lot of variants for playing Koi-koi, especially in regards to scoring. For Board Game Arena, two variants are provided through the options when creating the game: * - '''Soft "Koi!"''' is a variant adapted from [http://www.sloperama.com/hanafuda/rules.html the Sloperama site rules] which is all about saying "Koi!". Of course you run the risk of your opponent making a yaku and scoring for the month (round) before you can score yourself, but in exchange for that risk, each time you will get '''a multiplier''' so that if you manage to increase your score with another yaku, you will score a lot more. Also, a starting multiplier will be set for the month if some "Bright cards" have been drawn for the field when dealing for the month. So this is an aggressive variant with a lot of points available if you push your luck. * - '''Hard "Koi!"''' is a variant adapted from [https://web.archive.org/web/20120421175954/http://hanafubuki.org/koikoi.html the Hanafubuki site rules] which is less incitative to call "Koi!" since you won't get a multiplier just for saying "Koi!". Instead, '''your opponent''' will! If you say "Koi!" at least once, then if your opponent manages to score his score will be doubled. Still, at some point you'll risk it, because if you manage to improve your yaku to score 7 points or more, then '''your score''' will be doubled. Please also note how draws are handled: * - if a month ends by lack of cards in hand and no player has managed to form a yaku, the dealer for the month (first player) gets 6 points ('''"dealer's privilege"'''); * - if a month ends by lack of cards in hand and at least a player managed to form a yaku (and said "Koi!" to continue), it's a draw and nobody gets any points. == About "Viewing" yaku == A few variants have been implementend for the "Viewing the Moon" and "Viewing the Cherry Blossoms" yaku: * - '''Viewing yaku enabled''' : both yaku are available (this is the default) * - '''Rain ruins the party''' : if a player captures at least one card of November (rain), the party is ruined, both yaku are unavailable for this player * - '''Viewing yaku disabled''' : both yaku are unavailable. == About "First play" == Getting the first play (and thus being the first to choose from the field) is a nice advantage. Some variants have been made available upon request: * - '''Winner starts the next month''' : the winner for the current month gets to play first the next month (this is the default) * - '''Loser starts the next month''' : the player who lost this month gets to play first the next month * - '''Alternate starting player''' : the player who didn't get to play first this month will play first the following month. 37c19796b1ef59688bf2ada41af3eba77058ccd7 Gamehelplostcities 0 210 1762 1738 2016-02-01T20:54:28Z Unabstainer 3427 wikitext text/x-wiki '''КОЛОДА:''' Колода состоит из карт экспедиций пяти видов (цветов). Каждая экспедиция особого цвета и включает 9 карт достоинством от 2 до 10, а также 3 карты контрактов (инвестиций). То есть всего в колоде 5*(9+3)=60 карт. Каждый из двух игроков изначально получает по 8 карт. '''ЦЕЛЬ ИГРЫ:''' Задача простая - выкладывать карты экспедиций с руки на свою сторону поля и набрать больше очков, чем противник. '''ХОД ИГРЫ:''' В свой ход игрок должен ОБЯЗАТЕЛЬНО сделать два действия в следующем порядке: 1. СЫГРАТЬ КАРТУ ЭКСПЕДИЦИИ С РУКИ: либо на свою сторону поля, "продвигая" экспедицию; либо в середину поля, где находится сброс (также разделен по цветам). 2. ПОПОЛНИТЬ РУКУ: либо взяв верхнюю карту из сброса; либо взяв верхнюю карту из колоды. Карты, выкладываемые на свою сторону поля, должны идти в порядке увеличения их достоинства, но возможны пропуски. Например, после того как игрок выложил карту достоинством 3 красной экспедиции - карту 2 красной экспедиции он уже выложить не может. Зато может выложить карту 4 или сразу 5 или даже 10. Карты контрактов можно выкладывать только пока не были сыграны карты с цифрами. На одну экспедицию игрок может заложить до 3х контрактов. Не обязательно стартовать все 5 экспедиций. Но если хотя бы одна карта экспедиции определенного цвета сыграна игроком, эта экспедиция считается начатой, и за нее будут начисляться или вычитаться очки. '''ПОДСЧЕТ ОЧКОВ:''' Стоимость начала одной экспедиции - 20 очков. Каждый контракт удорожает экспедицию еще на 20 очков. Если в экспедицию выложены все три контракта - стоимость экспедиции уже 80 очков. Необходимо, чтобы экспедиция была коммерчески выигрышной, то есть, выкладывая цифровые карты, необходимо погасить стоимость экспедиции и получить "прибыль". Каждая выложенная цифровая карта приносит владельцу количество очков написанное на ней, умноженное на количество контрактов + 1. Тогда подсчет очков для каждой начатой экспедиции сводится к следующему: 1. Суммируются все цифровые карты этой экспедиции, выложенные на поле. 2. Вычитается 20. 3. Умножается на количество контрактов + 1. 4. Если в экспедиции оказалось 8 и более карт (включая контрактные) - бонус 20 очков. 941d50b1b4ba0c8c6d62d998b953529a2a93b4e2 1763 1762 2016-02-01T20:58:48Z Unabstainer 3427 wikitext text/x-wiki '''КОЛОДА:''' Колода состоит из карт экспедиций пяти видов (цветов). Каждая экспедиция особого цвета и включает 9 карт достоинством от 2 до 10, а также 3 карты контрактов (инвестиций). То есть всего в колоде 5*(9+3)=60 карт. Каждый из двух игроков изначально получает по 8 карт. '''ЦЕЛЬ ИГРЫ:''' Задача простая - выкладывать по очереди карты экспедиций с руки на свою сторону поля и набрать больше очков, чем противник. Оба игрока могут выкладывать экспедицию одного и того же цвета, только каждый на свою сторону поля. '''ХОД ИГРЫ:''' В свой ход игрок должен ОБЯЗАТЕЛЬНО сделать два действия в следующем порядке: 1. СЫГРАТЬ КАРТУ ЭКСПЕДИЦИИ С РУКИ: либо на свою сторону поля, "продвигая" экспедицию и получая очки; либо в середину поля, где находится сброс (также разделен по цветам). 2. ПОПОЛНИТЬ РУКУ: либо взяв верхнюю карту из сброса; либо взяв верхнюю карту из колоды. Карты, выкладываемые на свою сторону поля, должны идти в порядке увеличения их достоинства, но возможны пропуски. Например, после того как игрок выложил карту достоинством 3 красной экспедиции - карту 2 красной экспедиции он уже выложить не может. Зато может выложить карту 4 или сразу 5 или даже 10. Карты контрактов можно выкладывать только пока не были сыграны карты с цифрами. На одну экспедицию игрок может заложить от 0 до 3 контрактов. Не обязательно стартовать все 5 экспедиций. Но если хотя бы одна карта экспедиции определенного цвета сыграна игроком, эта экспедиция считается начатой, и за нее будут начисляться или вычитаться очки. '''ПОДСЧЕТ ОЧКОВ:''' Стоимость начала одной экспедиции 20 очков. Каждый контракт удорожает экспедицию еще на 20 очков. Если в экспедицию выложены все три контракта - стоимость экспедиции уже 80 очков. Необходимо, чтобы экспедиция была коммерчески выигрышной, то есть, выкладывая цифровые карты, необходимо погасить стоимость экспедиции и получить сверху "прибыль". Каждая выложенная цифровая карта приносит владельцу количество очков написанное на ней, умноженное на количество контрактов + 1. Подсчет очков для каждой начатой экспедиции сводится к следующему: 1. Суммируются все цифровые карты этой экспедиции, выложенные на поле. 2. Вычитается 20. 3. Умножается на количество контрактов + 1. 4. Если в экспедиции оказалось 8 и более карт (включая контрактные) - дополнительный бонус 20 очков. Unabstainer 507eb27baf766c8b6dee47f93bda715a02348401 1766 1763 2016-02-04T17:25:20Z Squarerootofthree 5668 wikitext text/x-wiki THE DECK: Each expedition (suit) contains 9 cards numbered 2-10, and 3 investment cards (handshakes). PLAY: On each player's turn, they must: 1. Either add one card to an expedition (suit) or discard one to the appropriate pile on the board. 2. Pick up the top card from the stock pile or from one discard pile. Both actions are mandatory. Cards must be added in ascending sequence, but gaps are permitted. Investment cards may precede a numerical card, but may not be added afterward. Players need not embark on all 5 expeditions; only those that are embarked on by a player count toward that player's score. The game ends immediately when the last card is picked up from the stock pile. SCORING: For every expedition embarked on: 1. Take the sum of all numbered cards 2. Subtract 20 3. Multiply by (number of investment cards + 1) 4. Add 20 if the expedition contains 8 or more cards Final score = sum of all expeditions embarked on (whether positive or negative) 15dbe8b50e965cbd318557f9503180ef20f98db6 1767 1766 2016-02-04T17:26:42Z Squarerootofthree 5668 wikitext text/x-wiki '''THE DECK:''' Each expedition (suit) contains 9 cards numbered 2-10, and 3 investment cards (handshakes). '''PLAY:''' On each player's turn, they must: 1. Either add one card to an expedition (suit) or discard one to the appropriate pile on the board. 2. Pick up the top card from the stock pile or from one discard pile. Both actions are mandatory. Cards must be added in ascending sequence, but gaps are permitted. Investment cards may precede a numerical card, but may not be added afterward. Players need not embark on all 5 expeditions; only those that are embarked on by a player count toward that player's score. The game ends immediately when the last card is picked up from the stock pile. '''SCORING:''' For every expedition embarked on: 1. Take the sum of all numbered cards 2. Subtract 20 3. Multiply by (number of investment cards + 1) 4. Add 20 if the expedition contains 8 or more cards Final score = sum of all expeditions embarked on (whether positive or negative) 98be09cba36c374b1e15da30d6ee811c4d00dca4 Main game logic: yourgamename.game.php 0 86 1765 1723 2016-02-04T10:06:15Z Een 3 /* Notify players */ tip on player name highlighting wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 79 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. Notifications sent between the game start (setupNewGame) and the end of the "action" method of the first active state will never reach their destination. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array. Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private data must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. Important: the variable for player name must be ${player_name} in order to be highlighted with the player color in the game log == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. == Player color preferences == BGA players (Club members) may now choose their preferred color for playing. For example, if they are used to play green for every board game, they can select "green" in their BGA preferences page. Making your game compatible with colors preferences is very easy and requires only 1 line of PHP and 1 configuration change : On your gameinfos.inc.php file, add the following lines : // Favorite colors support : if set to "true", support attribution of favorite colors based on player's preferences (see reattributeColorsBasedOnPreferences PHP method) 'favorite_colors_support' => true, Then, on your main <your_game>.game.php file, find the "reloadPlayersBasicInfos" call in your "setupNewGame" method and replace : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reloadPlayersBasicInfos(); By : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reattributeColorsBasedOnPreferences( $players, array( /* LIST HERE THE AVAILABLE COLORS OF YOUR GAME INSTEAD OF THESE ONES */"ff0000", "008000", "0000ff", "ffa500", "773300" ) ); self::reloadPlayersBasicInfos(); The "reattributeColorsBasedOnPreferences" method reattributes all colors, taking into account players color preferences and available colors. Note that you must update the colors to indicate the colors available for your game. 2 important remarks : * for some games (ex : Chess), the color has an influence on a mechanism of the game, most of the time by giving a special advantage to a player (ex : Starting the game). Color preference mechanism must NOT be used in such a case. * your logic should NEVER consider that the first player has the color X, that the second player has the color Y, and so on. If this is the case, your game will NOT be compatible with reattributeColorsBasedOnPreferences as this method attribute colors to players based on their preferences and not based as their order at the table. 6867a0d31537d49c56d6869d2983468c9772ee24 Gamehelptournay 0 143 1773 1541 2016-02-26T20:06:23Z Thfump 478 Added Summary of turn actions section wikitext text/x-wiki Thanks to Mark Johnson (Eeeville) for his Tournay card descriptions used in the BGA adaptation! The '''game ends''' when both of the following conditions are met, or if condition 1 is met by more than one player:<BR> <OL><LI>A player has filled 9 spaces with at least 2 visible prestige buildings.</LI> <LI> One Town Crier card more than the number of players has been revealed.</LI></OL> The last round is triggered at the beginning of the start player's turn and each player gets a normal turn in this round. Then all players can choose a final card to play into their districts. ===Summary of turn actions=== #Play a card from your hand (optional) #Perform an action with citizen(s) (mandatory) #*Draw a card #*Activate a building in your district #*Combat an event #*Earn deniers #*Gather your citizens on your plaza ===Details of prestige buildings=== * You cannot score more than 12 victory points from the same prestige building. * If two players build the same prestige building there is only a single scoring. '''Yellow:''' *'''Belfry''': per set (1 yellow + 1 white + 1 red) of buildings or characters *'''City Hall''': per yellow citizen (2x) *'''Cloth Hall''': per yellow building or character (2x) *'''Mint''': per set of 4 deniers (2x) *'''Tour des Six''': per character (2x) '''White:''' *'''Cathedral''': only the player who builds it earns 8 PPs. *'''La Madeleine''': per prestige building (2x) *'''Saint-Brice''': per set (1 yellow + 1 white + 1 red) of buildings or characters *'''Saint-Jacques''': per white building or character (2x) *'''Saint-Nicolas''': per set of citizens you own (1 yellow +1 white +1 red) *'''Saint-Quentin''': per white citizen (2x) '''Red:''' *'''Pont des Trous''': per set (1 yellow + 1 white + 1 red) of citizens *'''Porte de la Vigne''': per red citizen (2x) *'''Tour d’Arras''': per white and yellow building (2x) *'''Tour Henry VIII''': per rampart built (2x) *'''Tour Saint-Georges''': per red card building or character (2x) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="110" | Prestige Building ! align="center" width="50" | Colour ! align="center" width="20" | # ! align="center" width="50" | Cost to Play ! align="center" width="50" | Builder Points ! align="center" width="50" | Non-Builder Points ! align="center" width="225" | Condition |- | align="center" | '''Belfry''' | align="center" | Yellow | align="center" | 1 | align="center" | 5 deniers | align="center" | 4 | align="center" | 2 | align="center" | each set of visible buildings or characters<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''City Hall''' | align="center" | Yellow | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each yellow citizen owned |- | align="center" | '''Cloth Hall''' | align="center" | Yellow | align="center" | 2 | align="center" | 1 yellow citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible yellow building or character |- | align="center" | '''Mint''' | align="center" | Yellow | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each set of 4 deniers |- | align="center" | '''Tour des Six''' | align="center" | Yellow | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each visible character |- | align="center" | '''Cathedral''' | align="center" | White | align="center" | 1 | align="center" | 20 deniers | align="center" | 8 | align="center" | 0 | align="center" | none |- | align="center" | '''La Madeleine''' | align="center" | White | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each visible prestige building |- | align="center" | '''Saint-Brice''' | align="center" | White | align="center" | 1 | align="center" | 5 deniers | align="center" | 4 | align="center" | 2 | align="center" | each set of visible buildings or characters<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Saint-Jacques''' | align="center" | White | align="center" | 2 | align="center" | 1 white citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible white building or character |- | align="center" | '''Saint-Nicolas''' | align="center" | White | align="center" | 1 | align="center" | 5 deniers | align="center" | 3 | align="center" | 1 | align="center" | each set of citizens you own<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Saint-Quentin''' | align="center" | White | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each white citizen owned |- | align="center" | '''Pont des Trous''' | align="center" | Red | align="center" | 1 | align="center" | 5 deniers | align="center" | 3 | align="center" | 1 | align="center" | each set of citizens you own<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Porte de la Vigne''' | align="center" | Red | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each red citizen owned |- | align="center" | '''Tour d’Arras''' | align="center" | Red | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each visible white and yellow building |- | align="center" | '''Tour Henry VIII''' | align="center" | Red | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each rampart card built |- | align="center" | '''Tour Saint-Georges''' | align="center" | Red | align="center" | 2 | align="center" | 1 red citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible red building or character |} 39c0a37d22a38c1d9ff46ab4533a3178a85a423c 1774 1773 2016-02-26T20:11:12Z Thfump 478 Title for End game conditions wikitext text/x-wiki Thanks to Mark Johnson (Eeeville) for his Tournay card descriptions used in the BGA adaptation! ===End game conditions=== The game ends when both of the following conditions are met, or if condition 1 is met by more than one player: #A player has filled 9 spaces with at least 2 visible prestige buildings. #One Town Crier card more than the number of players has been revealed. The last round is triggered at the beginning of the start player's turn, and each player gets a normal turn in this round. Then all players can choose a final card to play into their districts. ===Summary of turn actions=== #Play a card from your hand (optional) #Perform an action with citizen(s) (mandatory) #*Draw a card #*Activate a building in your district #*Combat an event #*Earn deniers #*Gather your citizens on your plaza ===Details of prestige buildings=== * You cannot score more than 12 victory points from the same prestige building. * If two players build the same prestige building there is only a single scoring. '''Yellow:''' *'''Belfry''': per set (1 yellow + 1 white + 1 red) of buildings or characters *'''City Hall''': per yellow citizen (2x) *'''Cloth Hall''': per yellow building or character (2x) *'''Mint''': per set of 4 deniers (2x) *'''Tour des Six''': per character (2x) '''White:''' *'''Cathedral''': only the player who builds it earns 8 PPs. *'''La Madeleine''': per prestige building (2x) *'''Saint-Brice''': per set (1 yellow + 1 white + 1 red) of buildings or characters *'''Saint-Jacques''': per white building or character (2x) *'''Saint-Nicolas''': per set of citizens you own (1 yellow +1 white +1 red) *'''Saint-Quentin''': per white citizen (2x) '''Red:''' *'''Pont des Trous''': per set (1 yellow + 1 white + 1 red) of citizens *'''Porte de la Vigne''': per red citizen (2x) *'''Tour d’Arras''': per white and yellow building (2x) *'''Tour Henry VIII''': per rampart built (2x) *'''Tour Saint-Georges''': per red card building or character (2x) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="110" | Prestige Building ! align="center" width="50" | Colour ! align="center" width="20" | # ! align="center" width="50" | Cost to Play ! align="center" width="50" | Builder Points ! align="center" width="50" | Non-Builder Points ! align="center" width="225" | Condition |- | align="center" | '''Belfry''' | align="center" | Yellow | align="center" | 1 | align="center" | 5 deniers | align="center" | 4 | align="center" | 2 | align="center" | each set of visible buildings or characters<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''City Hall''' | align="center" | Yellow | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each yellow citizen owned |- | align="center" | '''Cloth Hall''' | align="center" | Yellow | align="center" | 2 | align="center" | 1 yellow citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible yellow building or character |- | align="center" | '''Mint''' | align="center" | Yellow | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each set of 4 deniers |- | align="center" | '''Tour des Six''' | align="center" | Yellow | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each visible character |- | align="center" | '''Cathedral''' | align="center" | White | align="center" | 1 | align="center" | 20 deniers | align="center" | 8 | align="center" | 0 | align="center" | none |- | align="center" | '''La Madeleine''' | align="center" | White | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each visible prestige building |- | align="center" | '''Saint-Brice''' | align="center" | White | align="center" | 1 | align="center" | 5 deniers | align="center" | 4 | align="center" | 2 | align="center" | each set of visible buildings or characters<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Saint-Jacques''' | align="center" | White | align="center" | 2 | align="center" | 1 white citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible white building or character |- | align="center" | '''Saint-Nicolas''' | align="center" | White | align="center" | 1 | align="center" | 5 deniers | align="center" | 3 | align="center" | 1 | align="center" | each set of citizens you own<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Saint-Quentin''' | align="center" | White | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each white citizen owned |- | align="center" | '''Pont des Trous''' | align="center" | Red | align="center" | 1 | align="center" | 5 deniers | align="center" | 3 | align="center" | 1 | align="center" | each set of citizens you own<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Porte de la Vigne''' | align="center" | Red | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each red citizen owned |- | align="center" | '''Tour d’Arras''' | align="center" | Red | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each visible white and yellow building |- | align="center" | '''Tour Henry VIII''' | align="center" | Red | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each rampart card built |- | align="center" | '''Tour Saint-Georges''' | align="center" | Red | align="center" | 2 | align="center" | 1 red citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible red building or character |} d5412b294f69b91f62116f7cf0701d64119fa447 1775 1774 2016-02-26T20:24:16Z Thfump 478 /* End game conditions */ wikitext text/x-wiki Thanks to Mark Johnson (Eeeville) for his Tournay card descriptions used in the BGA adaptation! ===End game conditions=== The game ends when both of the following conditions are met, or if condition 1 is met by more than one player: <ol><li>A player has filled 9 spaces with at least 2 visible prestige buildings.</li> <li>One Town Crier card more than the number of players has been revealed.</li></ol> The last round is triggered at the beginning of the start player's turn, and each player gets a normal turn in this round. Then all players can choose a final card to play into their districts. ===Summary of turn actions=== #Play a card from your hand (optional) #Perform an action with citizen(s) (mandatory) #*Draw a card #*Activate a building in your district #*Combat an event #*Earn deniers #*Gather your citizens on your plaza ===Details of prestige buildings=== * You cannot score more than 12 victory points from the same prestige building. * If two players build the same prestige building there is only a single scoring. '''Yellow:''' *'''Belfry''': per set (1 yellow + 1 white + 1 red) of buildings or characters *'''City Hall''': per yellow citizen (2x) *'''Cloth Hall''': per yellow building or character (2x) *'''Mint''': per set of 4 deniers (2x) *'''Tour des Six''': per character (2x) '''White:''' *'''Cathedral''': only the player who builds it earns 8 PPs. *'''La Madeleine''': per prestige building (2x) *'''Saint-Brice''': per set (1 yellow + 1 white + 1 red) of buildings or characters *'''Saint-Jacques''': per white building or character (2x) *'''Saint-Nicolas''': per set of citizens you own (1 yellow +1 white +1 red) *'''Saint-Quentin''': per white citizen (2x) '''Red:''' *'''Pont des Trous''': per set (1 yellow + 1 white + 1 red) of citizens *'''Porte de la Vigne''': per red citizen (2x) *'''Tour d’Arras''': per white and yellow building (2x) *'''Tour Henry VIII''': per rampart built (2x) *'''Tour Saint-Georges''': per red card building or character (2x) {|class="wikitable sortable" border="1" cellpadding="5" cellspacing="0" ! align="center" width="110" | Prestige Building ! align="center" width="50" | Colour ! align="center" width="20" | # ! align="center" width="50" | Cost to Play ! align="center" width="50" | Builder Points ! align="center" width="50" | Non-Builder Points ! align="center" width="225" | Condition |- | align="center" | '''Belfry''' | align="center" | Yellow | align="center" | 1 | align="center" | 5 deniers | align="center" | 4 | align="center" | 2 | align="center" | each set of visible buildings or characters<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''City Hall''' | align="center" | Yellow | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each yellow citizen owned |- | align="center" | '''Cloth Hall''' | align="center" | Yellow | align="center" | 2 | align="center" | 1 yellow citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible yellow building or character |- | align="center" | '''Mint''' | align="center" | Yellow | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each set of 4 deniers |- | align="center" | '''Tour des Six''' | align="center" | Yellow | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each visible character |- | align="center" | '''Cathedral''' | align="center" | White | align="center" | 1 | align="center" | 20 deniers | align="center" | 8 | align="center" | 0 | align="center" | none |- | align="center" | '''La Madeleine''' | align="center" | White | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each visible prestige building |- | align="center" | '''Saint-Brice''' | align="center" | White | align="center" | 1 | align="center" | 5 deniers | align="center" | 4 | align="center" | 2 | align="center" | each set of visible buildings or characters<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Saint-Jacques''' | align="center" | White | align="center" | 2 | align="center" | 1 white citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible white building or character |- | align="center" | '''Saint-Nicolas''' | align="center" | White | align="center" | 1 | align="center" | 5 deniers | align="center" | 3 | align="center" | 1 | align="center" | each set of citizens you own<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Saint-Quentin''' | align="center" | White | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each white citizen owned |- | align="center" | '''Pont des Trous''' | align="center" | Red | align="center" | 1 | align="center" | 5 deniers | align="center" | 3 | align="center" | 1 | align="center" | each set of citizens you own<BR> (1 yellow + 1 white + 1 red) |- | align="center" | '''Porte de la Vigne''' | align="center" | Red | align="center" | 2 | align="center" | 2 deniers,<BR> 1 card | align="center" | 2 | align="center" | 1 | align="center" | each red citizen owned |- | align="center" | '''Tour d’Arras''' | align="center" | Red | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each visible white and yellow building |- | align="center" | '''Tour Henry VIII''' | align="center" | Red | align="center" | 2 | align="center" | 5 deniers | align="center" | 2 | align="center" | 1 | align="center" | each rampart card built |- | align="center" | '''Tour Saint-Georges''' | align="center" | Red | align="center" | 2 | align="center" | 1 red citizen | align="center" | 2 | align="center" | 1 | align="center" | each visible red building or character |} dcd9dbf75edd04b3f093411b1cc57acc287dad6b Gamehelplogger 0 212 1776 2016-02-29T01:15:41Z Marcgenesis 10219 Created page with "From the official rules: == '''Background''' == Four rival lumberjacks are competing to chop down the most trees for their business. However, standing in their way are tr..." wikitext text/x-wiki From the official rules: == '''Background''' == Four rival lumberjacks are competing to chop down the most trees for their business. However, standing in their way are tree-hugging hippies protesting the deforestation. == '''Glossary''' == The following terms are used in Logger: '''Tree''' - Any seedling, sapling or mature tree on the board. '''Seedling''' - A large pyramid '''Sapling''' - A large pyramid with a medium pyramid stacked on it '''Mature Tree''' - A stack of pyramids. From top to bottom: small, medium, large. '''Protester''' - Denoted by a volcano cap '''Logger''' - A piece representing the player. Denoted by a medium pyramid of a color not used for trees. Non-Icehouse pieces like meeples may be also used. == '''Setup''' == Place a seedling on the center of the board. The remaining pyramid pieces from the Rainbow stash are kept aside in a common pool. Starting with the first player, each player places his logger on a corner of the board. Each player also starts with 1 protester in his or her supply (2 protesters for a 2-player game). Remember who went first as this will be important at the end game. == '''Goal''' == The winner is the player with the most points at the end of the game. Though scoring 10 points triggers the end game, having 10 points may not be enough for victory. == '''Gameplay''' == No Diagonals - Diagonals do not exist in Logger. Any rule pertaining to adjacency or movement is orthogonal only. Each player's turn consists of three parts: Movement, Growth and Action. Movement - Move your logger up to two spaces. Loggers may not occupy or walk through spaces occupied by trees or other loggers. Growth - All trees in the same row and column your logger occupies grow 1 stage. All seedlings become saplings and all saplings become mature trees. Mature trees produce 1 seedling in any space adjacent to them if able. Please note growth of all trees is considered simultaneous, so no tree should experience two stages of growth in one turn, nor should any seedlings newly spawned from a mature tree this turn. All trees in your logger's row and column must grow or create a new seedling if able. Action - There are three options in the Action phase: Plant, Protest and Chop. You must perform an action if able. This phase is skipped if your logger is unable to perform any action. Plant - Plant one seedling in any space adjacent to your logger. Protest - You may place one or more protesters from your supply onto mature trees. Protested trees may not be directly chopped down by any player. Chop - Chop down an unprotested mature tree adjacent to your logger by removing it from the board. Chopping will create a domino effect. Any mature tree behind the first chopped tree will also be considered chopped and so on regardless if they have protesters on them not. This process stops when either the edge of the board or a space occupied by anything other than a mature tree is reached. Score 1 point for each tree removed in this way. Add any protesters from felled trees to your supply. For example, a given row can have this formation: Player-Mature Tree-Mature Tree-Sapling-Mature Tree. When the player chops the first tree, the second one will be removed as well. However, the domino effect ends at the sapling because it is not fully mature. The sapling and the last mature tree remain on the board. == '''End Game''' == Logger is a game of equal turns. When a player reaches 10 points, the end game condition is reached. All players who have not had a turn this round will get one final turn. (Example: Player 2 reaches 10 points. Players 3 and 4 will receive one additional turn, but Player 1 does not. However, if Player 4 reaches 10 points, the game ends immediately.) The player with the most points at the end of the game wins. In case of a tie, the player with more protesters in reserve wins. 025baa9e42dbfc421a5ec9cd6af25422869b3670 Gamehelphive 0 167 1777 1600 2016-03-01T00:23:12Z Vrmlghost 10600 wikitext text/x-wiki Each turn, you may either place an insect or move an insect. All insects in play must be contiguous at all times. The first player's Queen Bee to be surrounded on all sides loses. You must place your Queen Bee by your fourth turn. Tournament opening rule: You cannot place your queen as your first move. Movement rules: * Queen Bee: Can only move one space * Beetle: Only one space, but it can move on top of another insect * Spider: 3 spaces in one direction * Grasshopper: Moves to the next open space in a straight line * Soldier Ant: It can move an unlimited amount along outside borders Expansion Pieces: * Mosquito: Uses the movement ability of any piece it is touching * Ladybug: Travels two spaces on top of other pieces and one space back down * Pill bug: Can move a single space, or move a piece* currently adjacent to it to another adjacent location * The pill bug isn't allowed to move the piece that just moved. Also, the piece that the pill bug moves isn't allowed to move on the very next turn This is just a brief summary of movement rules. This has a comprehensive overview of movement rules: http://boardgamegeek.com/thread/371756/hive-detailed-review 7ef044428ddbb0d59d78504711815ac55ae57e4a Gamehelpbackgammon 0 213 1778 2016-03-02T03:04:02Z Teapo 9709 First draft, hope it helps wikitext text/x-wiki '''Objective''' Players roll dice to advance their pieces into their home base, after completed, resume by rolling dice to remove their pieces from the board. First player to clear all pieces from the board wins. '''Setup''' The game has a fixed setup, with opponent mirrored arrangement. Each players hone row is opposite the other, and each will be moving in only one, opposite direction around the board (either clockwise or anti-clockwise). '''Play''' Each roll of two dice can be played to advance one piece both numbers in sum, or split play as each die to advance one piece respectively. Should any number roll as double, player is able to play that number four times, as board will allow. Pieces cannot be moved to land on any space occupied by two or more opposing pieces. Your own pieces may accumulate in any quantity on your own occupied spaces. '''Capture''' Any piece stacked two or more is safe from capture. Any piece single on a space is vulnerable. Rolling number combination to land your piece on exposed opponent piece is a capture and token must sit out of play until a number roll allows entry into opposing home row (i.e farthest from own). No other piece may be moved until all captured pieces have re-entered the game. 1abaadbeb38dd98c37724a01ebb1933cbf6be225 1780 1778 2016-03-03T13:15:20Z Teapo 9709 typo (home) wikitext text/x-wiki '''Objective''' Players roll dice to advance their pieces into their home base, after completed, resume by rolling dice to remove their pieces from the board. First player to clear all pieces from the board wins. '''Setup''' The game has a fixed setup, with opponent mirrored arrangement. Each players home row is opposite the other, and each will be moving in only one, opposite direction around the board (either clockwise or anti-clockwise). '''Play''' Each roll of two dice can be played to advance one piece both numbers in sum, or split play as each die to advance one piece respectively. Should any number roll as double, player is able to play that number four times, as board will allow. Pieces cannot be moved to land on any space occupied by two or more opposing pieces. Your own pieces may accumulate in any quantity on your own occupied spaces. '''Capture''' Any piece stacked two or more is safe from capture. Any piece single on a space is vulnerable. Rolling number combination to land your piece on exposed opponent piece is a capture and token must sit out of play until a number roll allows entry into opposing home row (i.e farthest from own). No other piece may be moved until all captured pieces have re-entered the game. f4654e226e4bae0821454b08b17646c44c4ed201 Implijer:Teapo 2 214 1779 2016-03-02T03:07:34Z Teapo 9709 Initial wikitext text/x-wiki Welcome to my page ''Teapo'' is short for teapot which was already taken. No other significance to this name other than perhaps allusion to shipping crops as in the board game Puerto Rico, which ironically does not ship tea. 195d2f79cb380e524956e5ad4550868d9d8fdc83 Contact us 0 9 1781 1021 2016-03-07T01:46:03Z Timmymike 11798 wikitext text/x-wiki '''Board Game Arena'''位於法國。. == 聯繫 e-mail == 聯繫(at)boardgamearena.com 我們收到 '''很多'''的e-mail.請不要發給我們e-mail因為以下這兩個原因: *如果你想回報一個錯誤,請到 [http://boardgamearena.com/#!bugs 錯誤回報系統] * 如果你想舉報一個不守BGA規則的玩家,請使用"檢舉這名玩家" (在他個人檔案首頁)的按鍵. ==以下為郵政地址== G. Isabelli 19 bd république 92 260 Fontenay-aux-Roses FRANCE +33 6 17 25 80 34 89837a79eb8189964c63941a9d7f30312488bc30 1782 1781 2016-03-07T01:47:32Z Timmymike 11798 wikitext text/x-wiki '''Board Game Arena'''位於法國。. == 聯繫 e-mail == 聯繫(到)boardgamearena.com 我們收到 '''很多'''的e-mail.請不要發給我們e-mail因為以下這兩個原因: *如果你想回報一個錯誤,請到 [http://boardgamearena.com/#!bugs 錯誤回報系統] * 如果你想舉報一個不守BGA規則的玩家,請使用"檢舉這名玩家" (在他個人檔案首頁)的按鍵. ==以下為郵政地址== G. Isabelli 19 bd république 92 260 Fontenay-aux-Roses FRANCE +33 6 17 25 80 34 c3ef09fb6b76eb59fd5348b29a79e1c644f11afd 1794 1782 2016-03-14T18:04:46Z Sourisdudesert 1 Reverted edits by [[Special:Contributions/Timmymike|Timmymike]] ([[User talk:Timmymike|talk]]) to last revision by [[User:Een|Een]] wikitext text/x-wiki '''Board Game Arena''' is located in France. == Contact e-mail == contact(at)boardgamearena.com We receive '''a lot''' of e-mails. Please do not send us an e-mail in any of these two cases: * If you want to report a bug, please do it in the [http://boardgamearena.com/#!bugs bug reporting system] * If you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile. == Postal address == G. Isabelli 19 bd république 92 260 Fontenay-aux-Roses FRANCE +33 6 17 25 80 34 980a98bd2ca063ac351422c896d84cf8920c62a0 Help 0 4 1783 1559 2016-03-07T17:44:27Z Imperix 8857 new games added wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] is the most complete source of help for BGA. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpsechsnimmt|6 Nimmt!]] * [[Gamehelpeightmastersrevenge|8 Master's Revenge]] * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpassyria|Assyria]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpbattleoflits|Battle of LITS]] * [[Gamehelpbombay|Bombay]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcheckers|Checkers]] * [[Gamehelpchess|Chess]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpcoltexpress|Colt Express]] * [[Gamehelpdarkagent|Dark Agent]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpelfenland|Elfenland]] * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] * [[Gamehelpflorenzacardgame|Florenza: The Card Game]] </td> <td valign="top"> * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphanabi|Hanabi]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpinjawara|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpk2|K2]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] * [[Gamehelpkeyflower|Keyflower]] * [[Gamehelpkoikoi|Koi-koi]] * [[Gamehelpkoryo|Koryŏ]] * [[Gamehelpledernierpeuple|Le Dernier Peuple]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelplordsofxidit|Lords of Xidit]] * [[Gamehelplostcities|Lost Cities]] * [[Gamehelpmachiavelli|Machiavelli]] </td> <td valign="top"> * [[Gamehelpmetromania|Metromania]] * [[Gamehelpnautilus|Nautilus]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpnoirkvi|Noir: Killer versus Inspector]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppolis|Polis: Fight for the Hegemony]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquantum|Quantum]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelptashkalar|Tash-Kalar]] * [[Gamehelptheboss|The Boss]] </td> <td valign="top"> * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpcarrara|The Palaces of Carrara]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpxiangqi|Xiangqi]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> 696f4724efae37190391aa7e699eaaff3ef10123 About Board Game Arena 0 5 1784 1483 2016-03-13T03:52:56Z Boermunds 11872 wikitext text/x-wiki With '''Board Game Arena''' you can play board games online with the whole world. Board Game Arena is a next generation game platform which makes online gaming simpler and more attractive: * Nothing to install: play straight from your browser, from anywhere, at anytime. * Real time: your opponents are online, you play "live" (note: you can also choose to play "turn-based" games with opponents that are not online at the same time than you). * Simple: if you know the game, then you know how to play online. * Free. Board Game Arena offers a [http://en.boardgamearena.com/#!gamelist growing selection of board and card games]. We specialize in modern adults games ("European style games"). This game platform has been designed to host any kind of game. This flexibility allows us to offer a '''new game every month'''. 95f8bb2494aab2ed958899c8f5829223730f9d8d Faq 0 3 1785 1654 2016-03-13T03:55:19Z Boermunds 11872 /* What is Board Game Arena? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from around the world. A selection of various board games and card games are available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and has spent their reflexion time. Can someone wake them up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for their turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as they need to about the next move... well as long as there is still some time left on the game clock, that is. * Then you can ask this player to confirm that he or she is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left the computer temporarily. * If the player is not coming back, you can skip their turn as soon as the clock is negative. This player will get a "leave" penalty and you will win "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give them a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from their profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 96135be8fe026f9a588d0358883854c1e0e21ece 1786 1785 2016-03-13T03:56:40Z Boermunds 11872 /* What do I need to play? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from around the world. A selection of various board games and card games are available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible, we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What are the games available on BGA?=== Board Game Arena offers a various selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and has spent their reflexion time. Can someone wake them up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for their turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as they need to about the next move... well as long as there is still some time left on the game clock, that is. * Then you can ask this player to confirm that he or she is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left the computer temporarily. * If the player is not coming back, you can skip their turn as soon as the clock is negative. This player will get a "leave" penalty and you will win "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give them a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from their profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 86a2413dfc67897aa515bb1b97a7dc02db3fd751 1787 1786 2016-03-13T03:57:32Z Boermunds 11872 /* What are the games available on BGA? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from around the world. A selection of various board games and card games are available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible, we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What games are available on BGA?=== Board Game Arena offers a selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games you can find players at any time of the day. For other games we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and has spent their reflexion time. Can someone wake them up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for their turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as they need to about the next move... well as long as there is still some time left on the game clock, that is. * Then you can ask this player to confirm that he or she is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left the computer temporarily. * If the player is not coming back, you can skip their turn as soon as the clock is negative. This player will get a "leave" penalty and you will win "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give them a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from their profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 7593da453c5f3d81ef57488867904a4482224de7 1788 1787 2016-03-13T03:58:42Z Boermunds 11872 /* I launched a new table but nobody is joining? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from around the world. A selection of various board games and card games are available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible, we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What games are available on BGA?=== Board Game Arena offers a selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games, you can find players at any time of day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, which is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players having joined the table. If you are the table administrator and can't launch the game, most of the time it's because there is not yet enough players joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also starts the game manually if the minimum number of required players has been reached. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and has spent their reflexion time. Can someone wake them up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for their turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as they need to about the next move... well as long as there is still some time left on the game clock, that is. * Then you can ask this player to confirm that he or she is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left the computer temporarily. * If the player is not coming back, you can skip their turn as soon as the clock is negative. This player will get a "leave" penalty and you will win "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give them a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from their profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) afc29a2c27da82a1812d11fc5ba746682d6688c2 1789 1788 2016-03-13T04:01:50Z Boermunds 11872 /* I joined a game. When does the game start? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from around the world. A selection of various board games and card games are available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible, we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What games are available on BGA?=== Board Game Arena offers a selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games, you can find players at any time of day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, who is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players who have joined the table. If you are the table administrator and can't launch the game, most of the time it's because there are not yet enough players who have joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also start the game manually any time after the minimum number of required players have joined. ===What is the meaning of the small color circle next to players names?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but did not perform any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and has spent their reflexion time. Can someone wake them up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for their turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as they need to about the next move... well as long as there is still some time left on the game clock, that is. * Then you can ask this player to confirm that he or she is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left the computer temporarily. * If the player is not coming back, you can skip their turn as soon as the clock is negative. This player will get a "leave" penalty and you will win "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give them a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from their profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 05146276d72ed98b4dddc5748ae900b733478aaf 1790 1789 2016-03-13T04:03:27Z Boermunds 11872 /* What is the meaning of the small color circle next to players names? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from around the world. A selection of various board games and card games are available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible, we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What games are available on BGA?=== Board Game Arena offers a selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games, you can find players at any time of day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, who is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players who have joined the table. If you are the table administrator and can't launch the game, most of the time it's because there are not yet enough players who have joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also start the game manually any time after the minimum number of required players have joined. ===What does the small colored circle next to a player's name mean?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but has not performed any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Where number of victory points is the following: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. This way, "50%" means that you win 50% of 2 players game, or 33% of 3 players game, etc. == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and has spent their reflexion time. Can someone wake them up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for their turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as they need to about the next move... well as long as there is still some time left on the game clock, that is. * Then you can ask this player to confirm that he or she is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left the computer temporarily. * If the player is not coming back, you can skip their turn as soon as the clock is negative. This player will get a "leave" penalty and you will win "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give them a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from their profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) dbc3f6d2b84f7a050ecf03cd716029842f5068d4 1791 1790 2016-03-13T04:17:32Z Boermunds 11872 /* What does the '% hits' statistic mean? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from around the world. A selection of various board games and card games are available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible, we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What games are available on BGA?=== Board Game Arena offers a selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games, you can find players at any time of day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, who is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players who have joined the table. If you are the table administrator and can't launch the game, most of the time it's because there are not yet enough players who have joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also start the game manually any time after the minimum number of required players have joined. ===What does the small colored circle next to a player's name mean?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but has not performed any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Players earn more victory points for winning a game that has more players (half a point per player). So: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. For example, a player who plays a three player game and wins a third of the time will have: "50% hits", while a player who plays a four person game and wins a third of the time, will have: "67% hits" == During the game == ===What is the meaning of the icons next to players names?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and has spent their reflexion time. Can someone wake them up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of the fact. If the situation does not evolve, it might be that this player has some connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (left the game or has been fired from the game). The game goes on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for their turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as they need to about the next move... well as long as there is still some time left on the game clock, that is. * Then you can ask this player to confirm that he or she is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left the computer temporarily. * If the player is not coming back, you can skip their turn as soon as the clock is negative. This player will get a "leave" penalty and you will win "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give them a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from their profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) cdf582daef9abb71b0f637cd563f983081d64869 1792 1791 2016-03-13T04:39:08Z Boermunds 11872 /* What is the meaning of the icons next to players names? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from around the world. A selection of various board games and card games are available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible, we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What games are available on BGA?=== Board Game Arena offers a selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games, you can find players at any time of day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, who is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players who have joined the table. If you are the table administrator and can't launch the game, most of the time it's because there are not yet enough players who have joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also start the game manually any time after the minimum number of required players have joined. ===What does the small colored circle next to a player's name mean?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but has not performed any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Players earn more victory points for winning a game that has more players (half a point per player). So: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. For example, a player who plays a three player game and wins a third of the time will have: "50% hits", while a player who plays a four person game and wins a third of the time, will have: "67% hits" == During the game == ===What do the icons next to players' names mean?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and has spent their reflection time. Can someone wake them up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of this fact. If the situation doesn't change, it might suggest that this player has a connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (has left the game or been fired from the game). The game is going on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for their turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as they need to about the next move... well as long as there is still some time left on the game clock, that is. * Then you can ask this player to confirm that he or she is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left the computer temporarily. * If the player is not coming back, you can skip their turn as soon as the clock is negative. This player will get a "leave" penalty and you will win "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give them a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from their profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 772140cc95a843f79d5c61614fbec0d3ad4d4af3 1793 1792 2016-03-13T04:39:41Z Boermunds 11872 /* What do the icons next to players' names mean? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from around the world. A selection of various board games and card games are available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible, we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What games are available on BGA?=== Board Game Arena offers a selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games, you can find players at any time of day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, who is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players who have joined the table. If you are the table administrator and can't launch the game, most of the time it's because there are not yet enough players who have joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also start the game manually any time after the minimum number of required players have joined. ===What does the small colored circle next to a player's name mean?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but has not performed any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Players earn more victory points for winning a game that has more players (half a point per player). So: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. For example, a player who plays a three player game and wins a third of the time will have: "50% hits", while a player who plays a four person game and wins a third of the time, will have: "67% hits" == During the game == ===What do the icons next to players' names mean?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and has used up their reflection time. Can someone wake them up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of this fact. If the situation doesn't change, it might suggest that this player has a connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (has left the game or been fired from the game). The game is going on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for their turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as they need to about the next move... well as long as there is still some time left on the game clock, that is. * Then you can ask this player to confirm that he or she is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left the computer temporarily. * If the player is not coming back, you can skip their turn as soon as the clock is negative. This player will get a "leave" penalty and you will win "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give them a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from their profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Yes we still work aside, and yes there is a huge work to be done here everyday. There is essentially Club membership, but this is not enough. What we'd like to do is basically continue like this because we think this "community based" approach is the best for BGA. What we are trying to do, in addition, is to find a way to create a commercial activity in game portal development, distinct from BGA. This way we could have a flexible work with a source of revenue, distinct from BGA, that allows us to finance the time we spent on BGA. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) 082a1f94a14a2d38f6bb385bd593c0510962cff8 Gamehelpkeyflower 0 215 1795 2016-03-18T06:41:50Z Nickycraft 11932 Created page with "'''the game'''[[Media:Example.ogg]]" wikitext text/x-wiki '''the game'''[[Media:Example.ogg]] d0f38e94d59270c46a9745c2c70f2115572c941a Gamehelpsaboteur 0 32 1796 1669 2016-03-22T21:40:32Z Jest phulin 3510 Added explanation of the variants from another wiki page wikitext text/x-wiki == Goal == Get as many gold nuggets as possible during the three rounds of the game. In order to do so, # if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards # if you are a '''saboteur''', you must, in association with other saboteurs, prevent the gold diggers to get to the treasure. Your role (gold digger or saboteur) will be randomly selected at the start of each round. == Rules summary == On your turn, you must click on a card from your hand to select it, then play this card or discard it. You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card. The cards are of several types: * 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card. * 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score). A player with a broken tool cannot play a Path card. * 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you. * 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know. Then click on "I have seen it" button at the top. * 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove. == Cards in play == * 44 'Path' cards * 9 'Sabotage' cards (three for each tool) * 6 'Repair a tool' cards (two for each tool) * 3 'Repair a tool among these two' cards (one for each combination of two tools) * 5 'Map' cards (one less than in the box set, as requested by the game author) * 3 'Rock fall' cards * 28 'Gold' cards ** 16 with one gold nugget ** 8 with two gold nuggets ** 4 with three gold nuggets == Roles == Roles are randomly selected among a set that depends upon the number of players: * with 3 players: 1 saboteur and 3 gold diggers * with 4 players: 1 saboteur and 4 gold diggers * with 5 players: 2 saboteurs and 4 gold diggers * with 6 players: 2 saboteurs and 5 gold diggers * with 7 players: 3 saboteurs and 5 gold diggers * with 8 players: 3 saboteurs and 6 gold diggers * with 9 players: 3 saboteurs and 7 gold diggers * with 10 players: 4 saboteurs and 7 gold diggers == Available variants == The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum! Two variants are about gold sharing: *'''Old Mine:''' the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed! *'''New mine:''' the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!) Two variants are about gameplay: *'''Competitive:''' the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose! *'''Selfish dwarf:''' one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded) '''Have a good game !''' de1a27b15b397233111af3158550bdc7ef8dc0b6 Gamehelptashkalar 0 177 1797 1702 2016-04-01T12:40:10Z Ernus 12057 /* Setup */ wikitext text/x-wiki == Game forms == On Board Game Arena, Tash-Kalar may be played by 2 to 4 players), and in 2 distinct forms : - '''The High Form''': Players score points for tasks and for legendary pieces currently on the board, only available for 2 players. - '''Deathmatch''': No tasks. Players score points for destroying enemy pieces, for summoning legendary beings, and when their opponents invoke a flare. Deathmatch can be played by 2 to 4 players. The actual board game also features team play in both forms. == Setup == Ogni giocatore inizia con 6 carte pescate a caso: 3 esseri del proprio mazzo, 2 leggendari e 1 impeto. Nella modalità "Forma Suprema", vengono rivelati 3 obiettivi correnti più 1 come prossimo obiettivo. Nella modalità "Duello Mortale", il giocatore che gioca per secondo piazza 1 pezzo comune di ogni colore nei quadrati marcati dell'Arena. == Game play == Players take turns in clockwise order, beginning with the starting player. Each turn, you have 2 actions. Exception: The starting player has only 1 action on his or her first turn. Possible actions: - '''Place 1 common piece''' of your color on any empty square. If you have none left to place, you begin this action by picking up 1 of your common or heroic pieces, then place it as a common piece. - '''Summon a being'''. (See below.) - '''Discard 1 being''' that you drew from your deck. If you do, you may also return one or more of your other cards to the bottoms of their decks. Actions can be done in any order. You can do more than one “place” or “summon” action per turn (but no more than one “discard” action). You have to use all your actions. You can invoke a flare (see below) before or after any action. Invoking a flare does not cost you an action. Finish your turn by drawing cards so that you end up with 3 beings from your deck, 2 legends, and 1 flare. If you draw the last card in your deck, you may end up with fewer than 3. '''High Form''': At the end of the turn, you may claim exactly 1 of the current tasks, if you meet its criteria. '''Deathmatch''': At the end of your turn, score points for destroyed enemy pieces: 2 points for legendary, 1 point for heroic, 1 point for each pair of common pieces. In Deathmatch Melee (3-4 players) you keep a separate count of colored points against each of your opponents. Your final score is the '''lowest''' of all your colored scores. You get no points for destroying your own pieces. You get no points for an un- paired common piece, but you can pair two common pieces in different colors. Also score 1 point (in the color of your choice) each time you summon a legend. (Upgrading a heroic piece does not count as “summoning a legend”.) == Summoning a being == To summon a being, use 1 action and do the following: - '''Play the card''' from your hand and choose a square on the board where your pieces match the pattern on the card. The pattern can be rotated (by 90, 180, or 270 degrees). Mirror images and flips also count as a match. The pieces used to summon the being can be the same rank as those depicted in the pattern or higher rank. Empty squares are not important to the pattern. - '''Place a piece of the indicated rank''' (upper left corner of the card) on the square indicated by the white-framed square in the pattern. This square may be empty, unless the pattern says it must be occupied by one of your pieces. If the square is occupied by a piece of the same rank or lower, destroy that piece when you put the new piece on the square. If the square is occupied by a piece of higher rank, you cannot summon the being. If all your pieces of that type are already on the board, you may still be able to summon the being by picking up a piece that is not required for the pattern and use it as the new piece. - Once the new piece is on the board, '''resolve the effect''' printed on the card. - After resolving the effect, discard the card. == Invoking a flare == You can invoke a flare on your turn before or after any action. To invoke a flare, you must meet at least one of the criteria: - You meet the upper criterion if one of your opponents has '''that many more upgraded pieces''' (heroic and legendary) on the board than you. - You meet the lower criterion if one of your opponents has '''that many more pieces (total)''' on the board than you. If you meet the upper criterion, you resolve the upper effect. If you meet the lower criterion, you resolve the lower effect. If you meet both, you resolve the upper effect first, then the lower. If you meet the criteria against several opponents, you choose against whom you compare. Once the card has been resolved, discard it. == Resolving effects of beings and flares == No other action can be taken and no flare can be invoked until the entire effect of the card is resolved. Some parts of an effect may be optional: - May indicates that a certain part of an effect is optional. - Up to always includes 0. Any parts that are not specified as optional are mandatory. If an effect cannot be performed fully, do the parts that can be done. When a card uses its own name, it is referring to the piece on the board that represents the summoned being. '''Keywords''': - Upgraded piece: a heroic or legendary piece. - Non-legendary piece: a common or heroic piece. - Piece: If a piece is not specified as belonging to you or an opponent, then the effect includes any player's piece. - Marked space: a colored space in the pattern. If the text does not refer to marked spaces, the colored spaces in the pattern are just illustrational. - Adjacent square: one of eight squares sharing an edge (orthogonally adjacent) or a corner (diagonally adjacent) with a given square. If the given square is not specified, assume it is the square currently occupied by the newly summoned piece. - Distance: the shortest number of moves required to get from one square to another. For example, adjacent squares are at distance 1. - Move: A move is always onto an adjacent square. A move onto an occupied square destroys the piece that was there. - Standard move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Combat move: This type of move can be only onto an empty square or a square occupied by a piece of equal or lower rank. - Standard leap and combat leap: A leap is the same as a move, except the square doesn’t have to be adjacent. If not specified, a leap can be onto any square on the board. - Place: Like the “place” action. However, if there is no piece of the specified color and rank available, the piece cannot be placed. - Upgrade: Legendary pieces cannot be upgraded. To upgrade a common piece, flip it over. To upgrade a heroic piece, remove it and replace it with a legendary piece. If none is available, the heroic piece cannot be upgraded. - Downgrade: Common pieces cannot be downgraded. To downgrade a heroic piece, flip it over. To downgrade a legendary piece, replace it with a heroic piece. If none is available, the legendary piece cannot be downgraded. - Destroy: To destroy a piece, remove it from the board. - Convert: To convert an enemy piece, replace it with one of your pieces of the same rank (unless a different rank is specified). When keeping track of '''how many enemy pieces you destroyed''', count pieces you destroyed during summoning, pieces you destroyed with moves and leaps, pieces you destroyed with a “destroy” effect, and pieces you converted. Neither upgrading nor downgrading ever counts as destroying a piece. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. ---- These rules are extracted from CGE's full rules for Tash-Kalar. 16500c6129ba1ede8736ec4bae10a5b3d53aeb97 1798 1797 2016-04-01T12:45:06Z Ernus 12057 /* Game forms */ wikitext text/x-wiki == Modalità di gioco == Su Board Game Arena, Tash-Kalar può essere giocato da 2 a 4 giocatori e in 2 distinte modalità: - "Forma Suprema": I giocatori realizzano punti quando completano un obiettivo corrente e per i pezzi leggendari presenti nell'Arena. Questa modalità è disponibile solo per 2 giocatori. - "Duello Mortale": Non ci sono obiettivi da completare. I giocatori realizzano punti distruggendo pedine nemiche, evocando creature leggendarie e quando l'avversario invoca una carta impeto. il Duello Mortale può essere giocato da 2 a 4 giocatori. Il gioco in scatola prevede anche modalità a squadra in entrambe le modalità. == Setup == Ogni giocatore inizia con 6 carte pescate a caso: 3 esseri del proprio mazzo, 2 leggendari e 1 impeto. Nella modalità "Forma Suprema", vengono rivelati 3 obiettivi correnti più 1 come prossimo obiettivo. Nella modalità "Duello Mortale", il giocatore che gioca per secondo piazza 1 pezzo comune di ogni colore nei quadrati marcati dell'Arena. == Game play == Players take turns in clockwise order, beginning with the starting player. Each turn, you have 2 actions. Exception: The starting player has only 1 action on his or her first turn. Possible actions: - '''Place 1 common piece''' of your color on any empty square. If you have none left to place, you begin this action by picking up 1 of your common or heroic pieces, then place it as a common piece. - '''Summon a being'''. (See below.) - '''Discard 1 being''' that you drew from your deck. If you do, you may also return one or more of your other cards to the bottoms of their decks. Actions can be done in any order. You can do more than one “place” or “summon” action per turn (but no more than one “discard” action). You have to use all your actions. You can invoke a flare (see below) before or after any action. Invoking a flare does not cost you an action. Finish your turn by drawing cards so that you end up with 3 beings from your deck, 2 legends, and 1 flare. If you draw the last card in your deck, you may end up with fewer than 3. '''High Form''': At the end of the turn, you may claim exactly 1 of the current tasks, if you meet its criteria. '''Deathmatch''': At the end of your turn, score points for destroyed enemy pieces: 2 points for legendary, 1 point for heroic, 1 point for each pair of common pieces. In Deathmatch Melee (3-4 players) you keep a separate count of colored points against each of your opponents. Your final score is the '''lowest''' of all your colored scores. You get no points for destroying your own pieces. You get no points for an un- paired common piece, but you can pair two common pieces in different colors. Also score 1 point (in the color of your choice) each time you summon a legend. (Upgrading a heroic piece does not count as “summoning a legend”.) == Summoning a being == To summon a being, use 1 action and do the following: - '''Play the card''' from your hand and choose a square on the board where your pieces match the pattern on the card. The pattern can be rotated (by 90, 180, or 270 degrees). Mirror images and flips also count as a match. The pieces used to summon the being can be the same rank as those depicted in the pattern or higher rank. Empty squares are not important to the pattern. - '''Place a piece of the indicated rank''' (upper left corner of the card) on the square indicated by the white-framed square in the pattern. This square may be empty, unless the pattern says it must be occupied by one of your pieces. If the square is occupied by a piece of the same rank or lower, destroy that piece when you put the new piece on the square. If the square is occupied by a piece of higher rank, you cannot summon the being. If all your pieces of that type are already on the board, you may still be able to summon the being by picking up a piece that is not required for the pattern and use it as the new piece. - Once the new piece is on the board, '''resolve the effect''' printed on the card. - After resolving the effect, discard the card. == Invoking a flare == You can invoke a flare on your turn before or after any action. To invoke a flare, you must meet at least one of the criteria: - You meet the upper criterion if one of your opponents has '''that many more upgraded pieces''' (heroic and legendary) on the board than you. - You meet the lower criterion if one of your opponents has '''that many more pieces (total)''' on the board than you. If you meet the upper criterion, you resolve the upper effect. If you meet the lower criterion, you resolve the lower effect. If you meet both, you resolve the upper effect first, then the lower. If you meet the criteria against several opponents, you choose against whom you compare. Once the card has been resolved, discard it. == Resolving effects of beings and flares == No other action can be taken and no flare can be invoked until the entire effect of the card is resolved. Some parts of an effect may be optional: - May indicates that a certain part of an effect is optional. - Up to always includes 0. Any parts that are not specified as optional are mandatory. If an effect cannot be performed fully, do the parts that can be done. When a card uses its own name, it is referring to the piece on the board that represents the summoned being. '''Keywords''': - Upgraded piece: a heroic or legendary piece. - Non-legendary piece: a common or heroic piece. - Piece: If a piece is not specified as belonging to you or an opponent, then the effect includes any player's piece. - Marked space: a colored space in the pattern. If the text does not refer to marked spaces, the colored spaces in the pattern are just illustrational. - Adjacent square: one of eight squares sharing an edge (orthogonally adjacent) or a corner (diagonally adjacent) with a given square. If the given square is not specified, assume it is the square currently occupied by the newly summoned piece. - Distance: the shortest number of moves required to get from one square to another. For example, adjacent squares are at distance 1. - Move: A move is always onto an adjacent square. A move onto an occupied square destroys the piece that was there. - Standard move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Combat move: This type of move can be only onto an empty square or a square occupied by a piece of equal or lower rank. - Standard leap and combat leap: A leap is the same as a move, except the square doesn’t have to be adjacent. If not specified, a leap can be onto any square on the board. - Place: Like the “place” action. However, if there is no piece of the specified color and rank available, the piece cannot be placed. - Upgrade: Legendary pieces cannot be upgraded. To upgrade a common piece, flip it over. To upgrade a heroic piece, remove it and replace it with a legendary piece. If none is available, the heroic piece cannot be upgraded. - Downgrade: Common pieces cannot be downgraded. To downgrade a heroic piece, flip it over. To downgrade a legendary piece, replace it with a heroic piece. If none is available, the legendary piece cannot be downgraded. - Destroy: To destroy a piece, remove it from the board. - Convert: To convert an enemy piece, replace it with one of your pieces of the same rank (unless a different rank is specified). When keeping track of '''how many enemy pieces you destroyed''', count pieces you destroyed during summoning, pieces you destroyed with moves and leaps, pieces you destroyed with a “destroy” effect, and pieces you converted. Neither upgrading nor downgrading ever counts as destroying a piece. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. ---- These rules are extracted from CGE's full rules for Tash-Kalar. 63c1bbc4234b7606379df61147abd38e9c74e692 1799 1798 2016-04-01T13:03:50Z Ernus 12057 /* Game play */ wikitext text/x-wiki == Modalità di gioco == Su Board Game Arena, Tash-Kalar può essere giocato da 2 a 4 giocatori e in 2 distinte modalità: - "Forma Suprema": I giocatori realizzano punti quando completano un obiettivo corrente e per i pezzi leggendari presenti nell'Arena. Questa modalità è disponibile solo per 2 giocatori. - "Duello Mortale": Non ci sono obiettivi da completare. I giocatori realizzano punti distruggendo pedine nemiche, evocando creature leggendarie e quando l'avversario invoca una carta impeto. il Duello Mortale può essere giocato da 2 a 4 giocatori. Il gioco in scatola prevede anche modalità a squadra in entrambe le modalità. == Setup == Ogni giocatore inizia con 6 carte pescate a caso: 3 esseri del proprio mazzo, 2 leggendari e 1 impeto. Nella modalità "Forma Suprema", vengono rivelati 3 obiettivi correnti più 1 come prossimo obiettivo. Nella modalità "Duello Mortale", il giocatore che gioca per secondo piazza 1 pezzo comune di ogni colore nei quadrati marcati dell'Arena. == Game play == Si comincia dal primo giocatore scelto a caso e si procede in senso orario. Ogni turno prevede 2 azioni, tranne il giocatore iniziale che ha solo 1 azione disponibile come primo turno. Azioni possibili: - '''"Piazzare 1 pezzo semplice"''' del tuo colore su un quadrato vuoto. Se non hai pezzi disponibili devi riprendere 1 dei tuoi pezzi semplici o eroici già piazzati sull'Arena in precedenza e dopo piazzarlo dove vuoi. - '''"Evocare un essere"'''. Leggi più avanti - '''"Scartare 1 carta essere del tuo mazzo"'''. Se lo fai puoi anche mettere una o più carte (anche leggendarie o impeti) in fondo al rispettivo mazzo di pesca. Le azioni possono essere eseguite in qualsiasi ordine. Puoi prima "piazzare" e poi "evocare" o viceversa (puoi fare una sola azione di scarto per turno). Devi sempre usare le tue azioni disponibili. Puoi invocare un impeto (leggi più avanti) prima o dopo un'azione. Invocare un impeto non costa nessuna azione. Il tuo turno finisce pescando altrettante carte di quante ne sono state giocate, in modo da avere sempre 3 carte essere del tuo mazzo, 2 leggendarie e i impeto. Se peschi l'ultima carta del tuo mazzo, potresti finire la partita anche con meno di 3 carte essere in mano. '''"Forma Suprema"''': Alla fine del tuo turno puoi completare solamente 1 dei compiti disponibili, se hai soddisfatto i suoi requisiti. '''"Duello Mortale"''': Alla fine del tuo turno, realizzi punti per le pedine nemiche distrutte: 2 punti per una leggendaria, 1 punto per un'eroica e 1 punto per ogni coppia di pedine semplici distrutte. Nella ''Mischia Mortale'' (3-4 giocatori) fai punti per ogni pedina nemica distrutta nei diversi colori. Il tuo punteggio finale è determinato dal colore nel quale hai il punteggio più basso. Non realizzi punti se distruggi tue pedine e per tutte le pedine semplici nemiche spaiate di un solo colore. Puoi appaiare 2 pedine semplici nemiche di diverso colore e decidere in quale colore realizzare i punti. Realizzi 1 punto (nel colore che preferisci) ogni volta che evochi 1 leggenda (promuovere un pezzo eroico non conta come un'evocazione leggendaria). Se il tuo avversario invoca 1 carta impeto tu guadagni 1 punto. == Summoning a being == To summon a being, use 1 action and do the following: - '''Play the card''' from your hand and choose a square on the board where your pieces match the pattern on the card. The pattern can be rotated (by 90, 180, or 270 degrees). Mirror images and flips also count as a match. The pieces used to summon the being can be the same rank as those depicted in the pattern or higher rank. Empty squares are not important to the pattern. - '''Place a piece of the indicated rank''' (upper left corner of the card) on the square indicated by the white-framed square in the pattern. This square may be empty, unless the pattern says it must be occupied by one of your pieces. If the square is occupied by a piece of the same rank or lower, destroy that piece when you put the new piece on the square. If the square is occupied by a piece of higher rank, you cannot summon the being. If all your pieces of that type are already on the board, you may still be able to summon the being by picking up a piece that is not required for the pattern and use it as the new piece. - Once the new piece is on the board, '''resolve the effect''' printed on the card. - After resolving the effect, discard the card. == Invoking a flare == You can invoke a flare on your turn before or after any action. To invoke a flare, you must meet at least one of the criteria: - You meet the upper criterion if one of your opponents has '''that many more upgraded pieces''' (heroic and legendary) on the board than you. - You meet the lower criterion if one of your opponents has '''that many more pieces (total)''' on the board than you. If you meet the upper criterion, you resolve the upper effect. If you meet the lower criterion, you resolve the lower effect. If you meet both, you resolve the upper effect first, then the lower. If you meet the criteria against several opponents, you choose against whom you compare. Once the card has been resolved, discard it. == Resolving effects of beings and flares == No other action can be taken and no flare can be invoked until the entire effect of the card is resolved. Some parts of an effect may be optional: - May indicates that a certain part of an effect is optional. - Up to always includes 0. Any parts that are not specified as optional are mandatory. If an effect cannot be performed fully, do the parts that can be done. When a card uses its own name, it is referring to the piece on the board that represents the summoned being. '''Keywords''': - Upgraded piece: a heroic or legendary piece. - Non-legendary piece: a common or heroic piece. - Piece: If a piece is not specified as belonging to you or an opponent, then the effect includes any player's piece. - Marked space: a colored space in the pattern. If the text does not refer to marked spaces, the colored spaces in the pattern are just illustrational. - Adjacent square: one of eight squares sharing an edge (orthogonally adjacent) or a corner (diagonally adjacent) with a given square. If the given square is not specified, assume it is the square currently occupied by the newly summoned piece. - Distance: the shortest number of moves required to get from one square to another. For example, adjacent squares are at distance 1. - Move: A move is always onto an adjacent square. A move onto an occupied square destroys the piece that was there. - Standard move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Combat move: This type of move can be only onto an empty square or a square occupied by a piece of equal or lower rank. - Standard leap and combat leap: A leap is the same as a move, except the square doesn’t have to be adjacent. If not specified, a leap can be onto any square on the board. - Place: Like the “place” action. However, if there is no piece of the specified color and rank available, the piece cannot be placed. - Upgrade: Legendary pieces cannot be upgraded. To upgrade a common piece, flip it over. To upgrade a heroic piece, remove it and replace it with a legendary piece. If none is available, the heroic piece cannot be upgraded. - Downgrade: Common pieces cannot be downgraded. To downgrade a heroic piece, flip it over. To downgrade a legendary piece, replace it with a heroic piece. If none is available, the legendary piece cannot be downgraded. - Destroy: To destroy a piece, remove it from the board. - Convert: To convert an enemy piece, replace it with one of your pieces of the same rank (unless a different rank is specified). When keeping track of '''how many enemy pieces you destroyed''', count pieces you destroyed during summoning, pieces you destroyed with moves and leaps, pieces you destroyed with a “destroy” effect, and pieces you converted. Neither upgrading nor downgrading ever counts as destroying a piece. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. ---- These rules are extracted from CGE's full rules for Tash-Kalar. 287d8edf672dfbeb4e041413fd490363a5c6369a 1800 1799 2016-04-01T13:04:11Z Ernus 12057 /* Setup */ wikitext text/x-wiki == Modalità di gioco == Su Board Game Arena, Tash-Kalar può essere giocato da 2 a 4 giocatori e in 2 distinte modalità: - "Forma Suprema": I giocatori realizzano punti quando completano un obiettivo corrente e per i pezzi leggendari presenti nell'Arena. Questa modalità è disponibile solo per 2 giocatori. - "Duello Mortale": Non ci sono obiettivi da completare. I giocatori realizzano punti distruggendo pedine nemiche, evocando creature leggendarie e quando l'avversario invoca una carta impeto. il Duello Mortale può essere giocato da 2 a 4 giocatori. Il gioco in scatola prevede anche modalità a squadra in entrambe le modalità. == Setup == Ogni giocatore inizia con 6 carte pescate a caso: 3 esseri del proprio mazzo, 2 leggendari e 1 impeto. Nella modalità '''"Forma Suprema"''', vengono rivelati 3 obiettivi correnti più 1 come prossimo obiettivo. Nella modalità '''"Duello Mortale"''', il giocatore che gioca per secondo piazza 1 pezzo comune di ogni colore nei quadrati marcati dell'Arena. == Game play == Si comincia dal primo giocatore scelto a caso e si procede in senso orario. Ogni turno prevede 2 azioni, tranne il giocatore iniziale che ha solo 1 azione disponibile come primo turno. Azioni possibili: - '''"Piazzare 1 pezzo semplice"''' del tuo colore su un quadrato vuoto. Se non hai pezzi disponibili devi riprendere 1 dei tuoi pezzi semplici o eroici già piazzati sull'Arena in precedenza e dopo piazzarlo dove vuoi. - '''"Evocare un essere"'''. Leggi più avanti - '''"Scartare 1 carta essere del tuo mazzo"'''. Se lo fai puoi anche mettere una o più carte (anche leggendarie o impeti) in fondo al rispettivo mazzo di pesca. Le azioni possono essere eseguite in qualsiasi ordine. Puoi prima "piazzare" e poi "evocare" o viceversa (puoi fare una sola azione di scarto per turno). Devi sempre usare le tue azioni disponibili. Puoi invocare un impeto (leggi più avanti) prima o dopo un'azione. Invocare un impeto non costa nessuna azione. Il tuo turno finisce pescando altrettante carte di quante ne sono state giocate, in modo da avere sempre 3 carte essere del tuo mazzo, 2 leggendarie e i impeto. Se peschi l'ultima carta del tuo mazzo, potresti finire la partita anche con meno di 3 carte essere in mano. '''"Forma Suprema"''': Alla fine del tuo turno puoi completare solamente 1 dei compiti disponibili, se hai soddisfatto i suoi requisiti. '''"Duello Mortale"''': Alla fine del tuo turno, realizzi punti per le pedine nemiche distrutte: 2 punti per una leggendaria, 1 punto per un'eroica e 1 punto per ogni coppia di pedine semplici distrutte. Nella ''Mischia Mortale'' (3-4 giocatori) fai punti per ogni pedina nemica distrutta nei diversi colori. Il tuo punteggio finale è determinato dal colore nel quale hai il punteggio più basso. Non realizzi punti se distruggi tue pedine e per tutte le pedine semplici nemiche spaiate di un solo colore. Puoi appaiare 2 pedine semplici nemiche di diverso colore e decidere in quale colore realizzare i punti. Realizzi 1 punto (nel colore che preferisci) ogni volta che evochi 1 leggenda (promuovere un pezzo eroico non conta come un'evocazione leggendaria). Se il tuo avversario invoca 1 carta impeto tu guadagni 1 punto. == Summoning a being == To summon a being, use 1 action and do the following: - '''Play the card''' from your hand and choose a square on the board where your pieces match the pattern on the card. The pattern can be rotated (by 90, 180, or 270 degrees). Mirror images and flips also count as a match. The pieces used to summon the being can be the same rank as those depicted in the pattern or higher rank. Empty squares are not important to the pattern. - '''Place a piece of the indicated rank''' (upper left corner of the card) on the square indicated by the white-framed square in the pattern. This square may be empty, unless the pattern says it must be occupied by one of your pieces. If the square is occupied by a piece of the same rank or lower, destroy that piece when you put the new piece on the square. If the square is occupied by a piece of higher rank, you cannot summon the being. If all your pieces of that type are already on the board, you may still be able to summon the being by picking up a piece that is not required for the pattern and use it as the new piece. - Once the new piece is on the board, '''resolve the effect''' printed on the card. - After resolving the effect, discard the card. == Invoking a flare == You can invoke a flare on your turn before or after any action. To invoke a flare, you must meet at least one of the criteria: - You meet the upper criterion if one of your opponents has '''that many more upgraded pieces''' (heroic and legendary) on the board than you. - You meet the lower criterion if one of your opponents has '''that many more pieces (total)''' on the board than you. If you meet the upper criterion, you resolve the upper effect. If you meet the lower criterion, you resolve the lower effect. If you meet both, you resolve the upper effect first, then the lower. If you meet the criteria against several opponents, you choose against whom you compare. Once the card has been resolved, discard it. == Resolving effects of beings and flares == No other action can be taken and no flare can be invoked until the entire effect of the card is resolved. Some parts of an effect may be optional: - May indicates that a certain part of an effect is optional. - Up to always includes 0. Any parts that are not specified as optional are mandatory. If an effect cannot be performed fully, do the parts that can be done. When a card uses its own name, it is referring to the piece on the board that represents the summoned being. '''Keywords''': - Upgraded piece: a heroic or legendary piece. - Non-legendary piece: a common or heroic piece. - Piece: If a piece is not specified as belonging to you or an opponent, then the effect includes any player's piece. - Marked space: a colored space in the pattern. If the text does not refer to marked spaces, the colored spaces in the pattern are just illustrational. - Adjacent square: one of eight squares sharing an edge (orthogonally adjacent) or a corner (diagonally adjacent) with a given square. If the given square is not specified, assume it is the square currently occupied by the newly summoned piece. - Distance: the shortest number of moves required to get from one square to another. For example, adjacent squares are at distance 1. - Move: A move is always onto an adjacent square. A move onto an occupied square destroys the piece that was there. - Standard move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Combat move: This type of move can be only onto an empty square or a square occupied by a piece of equal or lower rank. - Standard leap and combat leap: A leap is the same as a move, except the square doesn’t have to be adjacent. If not specified, a leap can be onto any square on the board. - Place: Like the “place” action. However, if there is no piece of the specified color and rank available, the piece cannot be placed. - Upgrade: Legendary pieces cannot be upgraded. To upgrade a common piece, flip it over. To upgrade a heroic piece, remove it and replace it with a legendary piece. If none is available, the heroic piece cannot be upgraded. - Downgrade: Common pieces cannot be downgraded. To downgrade a heroic piece, flip it over. To downgrade a legendary piece, replace it with a heroic piece. If none is available, the legendary piece cannot be downgraded. - Destroy: To destroy a piece, remove it from the board. - Convert: To convert an enemy piece, replace it with one of your pieces of the same rank (unless a different rank is specified). When keeping track of '''how many enemy pieces you destroyed''', count pieces you destroyed during summoning, pieces you destroyed with moves and leaps, pieces you destroyed with a “destroy” effect, and pieces you converted. Neither upgrading nor downgrading ever counts as destroying a piece. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. ---- These rules are extracted from CGE's full rules for Tash-Kalar. 3fcec6f7850c7cd2ac2fe93a8d1851f26ebb4bfe 1801 1800 2016-04-01T13:04:27Z Ernus 12057 /* Modalità di gioco */ wikitext text/x-wiki == Modalità di gioco == Su Board Game Arena, Tash-Kalar può essere giocato da 2 a 4 giocatori e in 2 distinte modalità: - '''"Forma Suprema":''' I giocatori realizzano punti quando completano un obiettivo corrente e per i pezzi leggendari presenti nell'Arena. Questa modalità è disponibile solo per 2 giocatori. - '''"Duello Mortale"''': Non ci sono obiettivi da completare. I giocatori realizzano punti distruggendo pedine nemiche, evocando creature leggendarie e quando l'avversario invoca una carta impeto. il Duello Mortale può essere giocato da 2 a 4 giocatori. Il gioco in scatola prevede anche modalità a squadra in entrambe le modalità. == Setup == Ogni giocatore inizia con 6 carte pescate a caso: 3 esseri del proprio mazzo, 2 leggendari e 1 impeto. Nella modalità '''"Forma Suprema"''', vengono rivelati 3 obiettivi correnti più 1 come prossimo obiettivo. Nella modalità '''"Duello Mortale"''', il giocatore che gioca per secondo piazza 1 pezzo comune di ogni colore nei quadrati marcati dell'Arena. == Game play == Si comincia dal primo giocatore scelto a caso e si procede in senso orario. Ogni turno prevede 2 azioni, tranne il giocatore iniziale che ha solo 1 azione disponibile come primo turno. Azioni possibili: - '''"Piazzare 1 pezzo semplice"''' del tuo colore su un quadrato vuoto. Se non hai pezzi disponibili devi riprendere 1 dei tuoi pezzi semplici o eroici già piazzati sull'Arena in precedenza e dopo piazzarlo dove vuoi. - '''"Evocare un essere"'''. Leggi più avanti - '''"Scartare 1 carta essere del tuo mazzo"'''. Se lo fai puoi anche mettere una o più carte (anche leggendarie o impeti) in fondo al rispettivo mazzo di pesca. Le azioni possono essere eseguite in qualsiasi ordine. Puoi prima "piazzare" e poi "evocare" o viceversa (puoi fare una sola azione di scarto per turno). Devi sempre usare le tue azioni disponibili. Puoi invocare un impeto (leggi più avanti) prima o dopo un'azione. Invocare un impeto non costa nessuna azione. Il tuo turno finisce pescando altrettante carte di quante ne sono state giocate, in modo da avere sempre 3 carte essere del tuo mazzo, 2 leggendarie e i impeto. Se peschi l'ultima carta del tuo mazzo, potresti finire la partita anche con meno di 3 carte essere in mano. '''"Forma Suprema"''': Alla fine del tuo turno puoi completare solamente 1 dei compiti disponibili, se hai soddisfatto i suoi requisiti. '''"Duello Mortale"''': Alla fine del tuo turno, realizzi punti per le pedine nemiche distrutte: 2 punti per una leggendaria, 1 punto per un'eroica e 1 punto per ogni coppia di pedine semplici distrutte. Nella ''Mischia Mortale'' (3-4 giocatori) fai punti per ogni pedina nemica distrutta nei diversi colori. Il tuo punteggio finale è determinato dal colore nel quale hai il punteggio più basso. Non realizzi punti se distruggi tue pedine e per tutte le pedine semplici nemiche spaiate di un solo colore. Puoi appaiare 2 pedine semplici nemiche di diverso colore e decidere in quale colore realizzare i punti. Realizzi 1 punto (nel colore che preferisci) ogni volta che evochi 1 leggenda (promuovere un pezzo eroico non conta come un'evocazione leggendaria). Se il tuo avversario invoca 1 carta impeto tu guadagni 1 punto. == Summoning a being == To summon a being, use 1 action and do the following: - '''Play the card''' from your hand and choose a square on the board where your pieces match the pattern on the card. The pattern can be rotated (by 90, 180, or 270 degrees). Mirror images and flips also count as a match. The pieces used to summon the being can be the same rank as those depicted in the pattern or higher rank. Empty squares are not important to the pattern. - '''Place a piece of the indicated rank''' (upper left corner of the card) on the square indicated by the white-framed square in the pattern. This square may be empty, unless the pattern says it must be occupied by one of your pieces. If the square is occupied by a piece of the same rank or lower, destroy that piece when you put the new piece on the square. If the square is occupied by a piece of higher rank, you cannot summon the being. If all your pieces of that type are already on the board, you may still be able to summon the being by picking up a piece that is not required for the pattern and use it as the new piece. - Once the new piece is on the board, '''resolve the effect''' printed on the card. - After resolving the effect, discard the card. == Invoking a flare == You can invoke a flare on your turn before or after any action. To invoke a flare, you must meet at least one of the criteria: - You meet the upper criterion if one of your opponents has '''that many more upgraded pieces''' (heroic and legendary) on the board than you. - You meet the lower criterion if one of your opponents has '''that many more pieces (total)''' on the board than you. If you meet the upper criterion, you resolve the upper effect. If you meet the lower criterion, you resolve the lower effect. If you meet both, you resolve the upper effect first, then the lower. If you meet the criteria against several opponents, you choose against whom you compare. Once the card has been resolved, discard it. == Resolving effects of beings and flares == No other action can be taken and no flare can be invoked until the entire effect of the card is resolved. Some parts of an effect may be optional: - May indicates that a certain part of an effect is optional. - Up to always includes 0. Any parts that are not specified as optional are mandatory. If an effect cannot be performed fully, do the parts that can be done. When a card uses its own name, it is referring to the piece on the board that represents the summoned being. '''Keywords''': - Upgraded piece: a heroic or legendary piece. - Non-legendary piece: a common or heroic piece. - Piece: If a piece is not specified as belonging to you or an opponent, then the effect includes any player's piece. - Marked space: a colored space in the pattern. If the text does not refer to marked spaces, the colored spaces in the pattern are just illustrational. - Adjacent square: one of eight squares sharing an edge (orthogonally adjacent) or a corner (diagonally adjacent) with a given square. If the given square is not specified, assume it is the square currently occupied by the newly summoned piece. - Distance: the shortest number of moves required to get from one square to another. For example, adjacent squares are at distance 1. - Move: A move is always onto an adjacent square. A move onto an occupied square destroys the piece that was there. - Standard move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Combat move: This type of move can be only onto an empty square or a square occupied by a piece of equal or lower rank. - Standard leap and combat leap: A leap is the same as a move, except the square doesn’t have to be adjacent. If not specified, a leap can be onto any square on the board. - Place: Like the “place” action. However, if there is no piece of the specified color and rank available, the piece cannot be placed. - Upgrade: Legendary pieces cannot be upgraded. To upgrade a common piece, flip it over. To upgrade a heroic piece, remove it and replace it with a legendary piece. If none is available, the heroic piece cannot be upgraded. - Downgrade: Common pieces cannot be downgraded. To downgrade a heroic piece, flip it over. To downgrade a legendary piece, replace it with a heroic piece. If none is available, the legendary piece cannot be downgraded. - Destroy: To destroy a piece, remove it from the board. - Convert: To convert an enemy piece, replace it with one of your pieces of the same rank (unless a different rank is specified). When keeping track of '''how many enemy pieces you destroyed''', count pieces you destroyed during summoning, pieces you destroyed with moves and leaps, pieces you destroyed with a “destroy” effect, and pieces you converted. Neither upgrading nor downgrading ever counts as destroying a piece. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. ---- These rules are extracted from CGE's full rules for Tash-Kalar. 6a5db42c3931181f6f85030ad18a0c4676c393a4 Gamehelptashkalar 0 177 1802 1801 2016-04-01T13:20:29Z Ernus 12057 /* Summoning a being */ wikitext text/x-wiki == Modalità di gioco == Su Board Game Arena, Tash-Kalar può essere giocato da 2 a 4 giocatori e in 2 distinte modalità: - '''"Forma Suprema":''' I giocatori realizzano punti quando completano un obiettivo corrente e per i pezzi leggendari presenti nell'Arena. Questa modalità è disponibile solo per 2 giocatori. - '''"Duello Mortale"''': Non ci sono obiettivi da completare. I giocatori realizzano punti distruggendo pedine nemiche, evocando creature leggendarie e quando l'avversario invoca una carta impeto. il Duello Mortale può essere giocato da 2 a 4 giocatori. Il gioco in scatola prevede anche modalità a squadra in entrambe le modalità. == Setup == Ogni giocatore inizia con 6 carte pescate a caso: 3 esseri del proprio mazzo, 2 leggendari e 1 impeto. Nella modalità '''"Forma Suprema"''', vengono rivelati 3 obiettivi correnti più 1 come prossimo obiettivo. Nella modalità '''"Duello Mortale"''', il giocatore che gioca per secondo piazza 1 pezzo comune di ogni colore nei quadrati marcati dell'Arena. == Game play == Si comincia dal primo giocatore scelto a caso e si procede in senso orario. Ogni turno prevede 2 azioni, tranne il giocatore iniziale che ha solo 1 azione disponibile come primo turno. Azioni possibili: - '''"Piazzare 1 pezzo semplice"''' del tuo colore su un quadrato vuoto. Se non hai pezzi disponibili devi riprendere 1 dei tuoi pezzi semplici o eroici già piazzati sull'Arena in precedenza e dopo piazzarlo dove vuoi. - '''"Evocare un essere"'''. Leggi più avanti - '''"Scartare 1 carta essere del tuo mazzo"'''. Se lo fai puoi anche mettere una o più carte (anche leggendarie o impeti) in fondo al rispettivo mazzo di pesca. Le azioni possono essere eseguite in qualsiasi ordine. Puoi prima "piazzare" e poi "evocare" o viceversa (puoi fare una sola azione di scarto per turno). Devi sempre usare le tue azioni disponibili. Puoi invocare un impeto (leggi più avanti) prima o dopo un'azione. Invocare un impeto non costa nessuna azione. Il tuo turno finisce pescando altrettante carte di quante ne sono state giocate, in modo da avere sempre 3 carte essere del tuo mazzo, 2 leggendarie e i impeto. Se peschi l'ultima carta del tuo mazzo, potresti finire la partita anche con meno di 3 carte essere in mano. '''"Forma Suprema"''': Alla fine del tuo turno puoi completare solamente 1 dei compiti disponibili, se hai soddisfatto i suoi requisiti. '''"Duello Mortale"''': Alla fine del tuo turno, realizzi punti per le pedine nemiche distrutte: 2 punti per una leggendaria, 1 punto per un'eroica e 1 punto per ogni coppia di pedine semplici distrutte. Nella ''Mischia Mortale'' (3-4 giocatori) fai punti per ogni pedina nemica distrutta nei diversi colori. Il tuo punteggio finale è determinato dal colore nel quale hai il punteggio più basso. Non realizzi punti se distruggi tue pedine e per tutte le pedine semplici nemiche spaiate di un solo colore. Puoi appaiare 2 pedine semplici nemiche di diverso colore e decidere in quale colore realizzare i punti. Realizzi 1 punto (nel colore che preferisci) ogni volta che evochi 1 leggenda (promuovere un pezzo eroico non conta come un'evocazione leggendaria). Se il tuo avversario invoca 1 carta impeto tu guadagni 1 punto. == Evocare una creatura == Per evocare una creatura, usa 1 azione in questo modo: - '''"Gioca una carta"''' dalla tua mano e scegli il quadrato sull'Arena che soddisfi la forma del pattern (disegno) richiesto sulla carta. Il pattern può essere ruotato (a 90, 180 o 270 gradi), specchiato e/o capovolto. I pezzi usati per evocare la creatura devono essere dello stesso grado (o maggiore) riportato sulla carta. I quadrati vuoti non sono essenziali per evocare la creatura. - '''"Piazza un pezzo del grado indicato"''' (in alto a sinistra sulla carta) sul quadrato marcato di bianco nel pattern. Questo quadrato può essere vuoto, a meno che il pattern non specifichi che debba essere occupato da un vostro pezzo. Se il quadrato è occupato da un pezzo dello stesso grado o inferiore, distruggilo, mettendo il nuovo pezzo al suo posto. Se il quadrato è occupato da un pezzo di grado superiore non puoi evocare l'essere in quel quadrato. Se tutti i pezzi di quel tipo sono già piazzati sull'Arena, puoi riprenderne uno di quelli non richiesti dal pattern in questione. - Quando il nuovo pezzo è piazzato sull'Arena '''"risolvi i suoi effetti"''' scritti sulla carta. - Dopo aver risolto gli effetti, scarta la carta. == Invoking a flare == You can invoke a flare on your turn before or after any action. To invoke a flare, you must meet at least one of the criteria: - You meet the upper criterion if one of your opponents has '''that many more upgraded pieces''' (heroic and legendary) on the board than you. - You meet the lower criterion if one of your opponents has '''that many more pieces (total)''' on the board than you. If you meet the upper criterion, you resolve the upper effect. If you meet the lower criterion, you resolve the lower effect. If you meet both, you resolve the upper effect first, then the lower. If you meet the criteria against several opponents, you choose against whom you compare. Once the card has been resolved, discard it. == Resolving effects of beings and flares == No other action can be taken and no flare can be invoked until the entire effect of the card is resolved. Some parts of an effect may be optional: - May indicates that a certain part of an effect is optional. - Up to always includes 0. Any parts that are not specified as optional are mandatory. If an effect cannot be performed fully, do the parts that can be done. When a card uses its own name, it is referring to the piece on the board that represents the summoned being. '''Keywords''': - Upgraded piece: a heroic or legendary piece. - Non-legendary piece: a common or heroic piece. - Piece: If a piece is not specified as belonging to you or an opponent, then the effect includes any player's piece. - Marked space: a colored space in the pattern. If the text does not refer to marked spaces, the colored spaces in the pattern are just illustrational. - Adjacent square: one of eight squares sharing an edge (orthogonally adjacent) or a corner (diagonally adjacent) with a given square. If the given square is not specified, assume it is the square currently occupied by the newly summoned piece. - Distance: the shortest number of moves required to get from one square to another. For example, adjacent squares are at distance 1. - Move: A move is always onto an adjacent square. A move onto an occupied square destroys the piece that was there. - Standard move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Combat move: This type of move can be only onto an empty square or a square occupied by a piece of equal or lower rank. - Standard leap and combat leap: A leap is the same as a move, except the square doesn’t have to be adjacent. If not specified, a leap can be onto any square on the board. - Place: Like the “place” action. However, if there is no piece of the specified color and rank available, the piece cannot be placed. - Upgrade: Legendary pieces cannot be upgraded. To upgrade a common piece, flip it over. To upgrade a heroic piece, remove it and replace it with a legendary piece. If none is available, the heroic piece cannot be upgraded. - Downgrade: Common pieces cannot be downgraded. To downgrade a heroic piece, flip it over. To downgrade a legendary piece, replace it with a heroic piece. If none is available, the legendary piece cannot be downgraded. - Destroy: To destroy a piece, remove it from the board. - Convert: To convert an enemy piece, replace it with one of your pieces of the same rank (unless a different rank is specified). When keeping track of '''how many enemy pieces you destroyed''', count pieces you destroyed during summoning, pieces you destroyed with moves and leaps, pieces you destroyed with a “destroy” effect, and pieces you converted. Neither upgrading nor downgrading ever counts as destroying a piece. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. ---- These rules are extracted from CGE's full rules for Tash-Kalar. b657493af6be360693936d2879cae938ed36ba8b 1803 1802 2016-04-01T13:21:28Z Ernus 12057 /* Game play */ wikitext text/x-wiki == Modalità di gioco == Su Board Game Arena, Tash-Kalar può essere giocato da 2 a 4 giocatori e in 2 distinte modalità: - '''"Forma Suprema":''' I giocatori realizzano punti quando completano un obiettivo corrente e per i pezzi leggendari presenti nell'Arena. Questa modalità è disponibile solo per 2 giocatori. - '''"Duello Mortale"''': Non ci sono obiettivi da completare. I giocatori realizzano punti distruggendo pedine nemiche, evocando creature leggendarie e quando l'avversario invoca una carta impeto. il Duello Mortale può essere giocato da 2 a 4 giocatori. Il gioco in scatola prevede anche modalità a squadra in entrambe le modalità. == Setup == Ogni giocatore inizia con 6 carte pescate a caso: 3 esseri del proprio mazzo, 2 leggendari e 1 impeto. Nella modalità '''"Forma Suprema"''', vengono rivelati 3 obiettivi correnti più 1 come prossimo obiettivo. Nella modalità '''"Duello Mortale"''', il giocatore che gioca per secondo piazza 1 pezzo comune di ogni colore nei quadrati marcati dell'Arena. == Game play == Si comincia dal primo giocatore scelto a caso e si procede in senso orario. Ogni turno prevede 2 azioni, tranne il giocatore iniziale che ha solo 1 azione disponibile come primo turno. Azioni possibili: - '''"Piazzare 1 pezzo semplice"''' del tuo colore su un quadrato vuoto. Se non hai pezzi disponibili devi riprendere 1 dei tuoi pezzi semplici o eroici già piazzati sull'Arena in precedenza e dopo piazzarlo dove vuoi. - '''"Evocare una cretura"'''. Leggi più avanti - '''"Scartare 1 carta creatura del tuo mazzo"'''. Se lo fai puoi anche mettere una o più carte (anche leggendarie o impeti) in fondo al rispettivo mazzo di pesca. Le azioni possono essere eseguite in qualsiasi ordine. Puoi prima "piazzare" e poi "evocare" o viceversa (puoi fare una sola azione di scarto per turno). Devi sempre usare le tue azioni disponibili. Puoi invocare un impeto (leggi più avanti) prima o dopo un'azione. Invocare un impeto non costa nessuna azione. Il tuo turno finisce pescando altrettante carte di quante ne sono state giocate, in modo da avere sempre 3 carte creatura del tuo mazzo, 2 leggendarie e i impeto. Se peschi l'ultima carta del tuo mazzo, potresti finire la partita anche con meno di 3 carte essere in mano. '''"Forma Suprema"''': Alla fine del tuo turno puoi completare solamente 1 dei compiti disponibili, se hai soddisfatto i suoi requisiti. '''"Duello Mortale"''': Alla fine del tuo turno, realizzi punti per le pedine nemiche distrutte: 2 punti per una leggendaria, 1 punto per un'eroica e 1 punto per ogni coppia di pedine semplici distrutte. Nella ''Mischia Mortale'' (3-4 giocatori) fai punti per ogni pedina nemica distrutta nei diversi colori. Il tuo punteggio finale è determinato dal colore nel quale hai il punteggio più basso. Non realizzi punti se distruggi tue pedine e per tutte le pedine semplici nemiche spaiate di un solo colore. Puoi appaiare 2 pedine semplici nemiche di diverso colore e decidere in quale colore realizzare i punti. Realizzi 1 punto (nel colore che preferisci) ogni volta che evochi 1 leggenda (promuovere un pezzo eroico non conta come un'evocazione leggendaria). Se il tuo avversario invoca 1 carta impeto tu guadagni 1 punto. == Evocare una creatura == Per evocare una creatura, usa 1 azione in questo modo: - '''"Gioca una carta"''' dalla tua mano e scegli il quadrato sull'Arena che soddisfi la forma del pattern (disegno) richiesto sulla carta. Il pattern può essere ruotato (a 90, 180 o 270 gradi), specchiato e/o capovolto. I pezzi usati per evocare la creatura devono essere dello stesso grado (o maggiore) riportato sulla carta. I quadrati vuoti non sono essenziali per evocare la creatura. - '''"Piazza un pezzo del grado indicato"''' (in alto a sinistra sulla carta) sul quadrato marcato di bianco nel pattern. Questo quadrato può essere vuoto, a meno che il pattern non specifichi che debba essere occupato da un vostro pezzo. Se il quadrato è occupato da un pezzo dello stesso grado o inferiore, distruggilo, mettendo il nuovo pezzo al suo posto. Se il quadrato è occupato da un pezzo di grado superiore non puoi evocare l'essere in quel quadrato. Se tutti i pezzi di quel tipo sono già piazzati sull'Arena, puoi riprenderne uno di quelli non richiesti dal pattern in questione. - Quando il nuovo pezzo è piazzato sull'Arena '''"risolvi i suoi effetti"''' scritti sulla carta. - Dopo aver risolto gli effetti, scarta la carta. == Invoking a flare == You can invoke a flare on your turn before or after any action. To invoke a flare, you must meet at least one of the criteria: - You meet the upper criterion if one of your opponents has '''that many more upgraded pieces''' (heroic and legendary) on the board than you. - You meet the lower criterion if one of your opponents has '''that many more pieces (total)''' on the board than you. If you meet the upper criterion, you resolve the upper effect. If you meet the lower criterion, you resolve the lower effect. If you meet both, you resolve the upper effect first, then the lower. If you meet the criteria against several opponents, you choose against whom you compare. Once the card has been resolved, discard it. == Resolving effects of beings and flares == No other action can be taken and no flare can be invoked until the entire effect of the card is resolved. Some parts of an effect may be optional: - May indicates that a certain part of an effect is optional. - Up to always includes 0. Any parts that are not specified as optional are mandatory. If an effect cannot be performed fully, do the parts that can be done. When a card uses its own name, it is referring to the piece on the board that represents the summoned being. '''Keywords''': - Upgraded piece: a heroic or legendary piece. - Non-legendary piece: a common or heroic piece. - Piece: If a piece is not specified as belonging to you or an opponent, then the effect includes any player's piece. - Marked space: a colored space in the pattern. If the text does not refer to marked spaces, the colored spaces in the pattern are just illustrational. - Adjacent square: one of eight squares sharing an edge (orthogonally adjacent) or a corner (diagonally adjacent) with a given square. If the given square is not specified, assume it is the square currently occupied by the newly summoned piece. - Distance: the shortest number of moves required to get from one square to another. For example, adjacent squares are at distance 1. - Move: A move is always onto an adjacent square. A move onto an occupied square destroys the piece that was there. - Standard move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Combat move: This type of move can be only onto an empty square or a square occupied by a piece of equal or lower rank. - Standard leap and combat leap: A leap is the same as a move, except the square doesn’t have to be adjacent. If not specified, a leap can be onto any square on the board. - Place: Like the “place” action. However, if there is no piece of the specified color and rank available, the piece cannot be placed. - Upgrade: Legendary pieces cannot be upgraded. To upgrade a common piece, flip it over. To upgrade a heroic piece, remove it and replace it with a legendary piece. If none is available, the heroic piece cannot be upgraded. - Downgrade: Common pieces cannot be downgraded. To downgrade a heroic piece, flip it over. To downgrade a legendary piece, replace it with a heroic piece. If none is available, the legendary piece cannot be downgraded. - Destroy: To destroy a piece, remove it from the board. - Convert: To convert an enemy piece, replace it with one of your pieces of the same rank (unless a different rank is specified). When keeping track of '''how many enemy pieces you destroyed''', count pieces you destroyed during summoning, pieces you destroyed with moves and leaps, pieces you destroyed with a “destroy” effect, and pieces you converted. Neither upgrading nor downgrading ever counts as destroying a piece. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. ---- These rules are extracted from CGE's full rules for Tash-Kalar. 0afd99c90c38854344743f0242e18a1957bd2fa5 1804 1803 2016-04-01T13:28:37Z Ernus 12057 /* Invoking a flare */ wikitext text/x-wiki == Modalità di gioco == Su Board Game Arena, Tash-Kalar può essere giocato da 2 a 4 giocatori e in 2 distinte modalità: - '''"Forma Suprema":''' I giocatori realizzano punti quando completano un obiettivo corrente e per i pezzi leggendari presenti nell'Arena. Questa modalità è disponibile solo per 2 giocatori. - '''"Duello Mortale"''': Non ci sono obiettivi da completare. I giocatori realizzano punti distruggendo pedine nemiche, evocando creature leggendarie e quando l'avversario invoca una carta impeto. il Duello Mortale può essere giocato da 2 a 4 giocatori. Il gioco in scatola prevede anche modalità a squadra in entrambe le modalità. == Setup == Ogni giocatore inizia con 6 carte pescate a caso: 3 esseri del proprio mazzo, 2 leggendari e 1 impeto. Nella modalità '''"Forma Suprema"''', vengono rivelati 3 obiettivi correnti più 1 come prossimo obiettivo. Nella modalità '''"Duello Mortale"''', il giocatore che gioca per secondo piazza 1 pezzo comune di ogni colore nei quadrati marcati dell'Arena. == Game play == Si comincia dal primo giocatore scelto a caso e si procede in senso orario. Ogni turno prevede 2 azioni, tranne il giocatore iniziale che ha solo 1 azione disponibile come primo turno. Azioni possibili: - '''"Piazzare 1 pezzo semplice"''' del tuo colore su un quadrato vuoto. Se non hai pezzi disponibili devi riprendere 1 dei tuoi pezzi semplici o eroici già piazzati sull'Arena in precedenza e dopo piazzarlo dove vuoi. - '''"Evocare una cretura"'''. Leggi più avanti - '''"Scartare 1 carta creatura del tuo mazzo"'''. Se lo fai puoi anche mettere una o più carte (anche leggendarie o impeti) in fondo al rispettivo mazzo di pesca. Le azioni possono essere eseguite in qualsiasi ordine. Puoi prima "piazzare" e poi "evocare" o viceversa (puoi fare una sola azione di scarto per turno). Devi sempre usare le tue azioni disponibili. Puoi invocare un impeto (leggi più avanti) prima o dopo un'azione. Invocare un impeto non costa nessuna azione. Il tuo turno finisce pescando altrettante carte di quante ne sono state giocate, in modo da avere sempre 3 carte creatura del tuo mazzo, 2 leggendarie e i impeto. Se peschi l'ultima carta del tuo mazzo, potresti finire la partita anche con meno di 3 carte essere in mano. '''"Forma Suprema"''': Alla fine del tuo turno puoi completare solamente 1 dei compiti disponibili, se hai soddisfatto i suoi requisiti. '''"Duello Mortale"''': Alla fine del tuo turno, realizzi punti per le pedine nemiche distrutte: 2 punti per una leggendaria, 1 punto per un'eroica e 1 punto per ogni coppia di pedine semplici distrutte. Nella ''Mischia Mortale'' (3-4 giocatori) fai punti per ogni pedina nemica distrutta nei diversi colori. Il tuo punteggio finale è determinato dal colore nel quale hai il punteggio più basso. Non realizzi punti se distruggi tue pedine e per tutte le pedine semplici nemiche spaiate di un solo colore. Puoi appaiare 2 pedine semplici nemiche di diverso colore e decidere in quale colore realizzare i punti. Realizzi 1 punto (nel colore che preferisci) ogni volta che evochi 1 leggenda (promuovere un pezzo eroico non conta come un'evocazione leggendaria). Se il tuo avversario invoca 1 carta impeto tu guadagni 1 punto. == Evocare una creatura == Per evocare una creatura, usa 1 azione in questo modo: - '''"Gioca una carta"''' dalla tua mano e scegli il quadrato sull'Arena che soddisfi la forma del pattern (disegno) richiesto sulla carta. Il pattern può essere ruotato (a 90, 180 o 270 gradi), specchiato e/o capovolto. I pezzi usati per evocare la creatura devono essere dello stesso grado (o maggiore) riportato sulla carta. I quadrati vuoti non sono essenziali per evocare la creatura. - '''"Piazza un pezzo del grado indicato"''' (in alto a sinistra sulla carta) sul quadrato marcato di bianco nel pattern. Questo quadrato può essere vuoto, a meno che il pattern non specifichi che debba essere occupato da un vostro pezzo. Se il quadrato è occupato da un pezzo dello stesso grado o inferiore, distruggilo, mettendo il nuovo pezzo al suo posto. Se il quadrato è occupato da un pezzo di grado superiore non puoi evocare l'essere in quel quadrato. Se tutti i pezzi di quel tipo sono già piazzati sull'Arena, puoi riprenderne uno di quelli non richiesti dal pattern in questione. - Quando il nuovo pezzo è piazzato sull'Arena '''"risolvi i suoi effetti"''' scritti sulla carta. - Dopo aver risolto gli effetti, scarta la carta. == Invocare un Impeto == Puoi invocare una carta impeto durnte il tuo turno prima o dopo una qualsiasi azione. Per invocare l'impeto devi soddisfare almeno uno dei due criteri scritti sulla carta: - Soddisfi il criterio stampato in alto sulla carta se il tuo avversario ha almeno quel numero di pezzi promossi (eroici e leggendari) più di te nell'Arena. - Soddisfi il criterio stampato in basso sulla carta se il tuo avversario ha almeno quel numero di pezzi totali (semplici, eroici e leggendari) più di te nell'Arena. Se si verificano una o tutte e due condizioni scritte sulla carta puoi risolverne gli effetti. Se soddisfi i criteri contro più avversari scegli contro chi comparare la carta (e quindi assegnare l'eventuale punto nei Duelli Mortali). Una volta che la carta è stata utilizzata bisogna scartarla. == Resolving effects of beings and flares == No other action can be taken and no flare can be invoked until the entire effect of the card is resolved. Some parts of an effect may be optional: - May indicates that a certain part of an effect is optional. - Up to always includes 0. Any parts that are not specified as optional are mandatory. If an effect cannot be performed fully, do the parts that can be done. When a card uses its own name, it is referring to the piece on the board that represents the summoned being. '''Keywords''': - Upgraded piece: a heroic or legendary piece. - Non-legendary piece: a common or heroic piece. - Piece: If a piece is not specified as belonging to you or an opponent, then the effect includes any player's piece. - Marked space: a colored space in the pattern. If the text does not refer to marked spaces, the colored spaces in the pattern are just illustrational. - Adjacent square: one of eight squares sharing an edge (orthogonally adjacent) or a corner (diagonally adjacent) with a given square. If the given square is not specified, assume it is the square currently occupied by the newly summoned piece. - Distance: the shortest number of moves required to get from one square to another. For example, adjacent squares are at distance 1. - Move: A move is always onto an adjacent square. A move onto an occupied square destroys the piece that was there. - Standard move: This type of move can be only onto an empty square or a square occupied by a piece of lower rank. - Combat move: This type of move can be only onto an empty square or a square occupied by a piece of equal or lower rank. - Standard leap and combat leap: A leap is the same as a move, except the square doesn’t have to be adjacent. If not specified, a leap can be onto any square on the board. - Place: Like the “place” action. However, if there is no piece of the specified color and rank available, the piece cannot be placed. - Upgrade: Legendary pieces cannot be upgraded. To upgrade a common piece, flip it over. To upgrade a heroic piece, remove it and replace it with a legendary piece. If none is available, the heroic piece cannot be upgraded. - Downgrade: Common pieces cannot be downgraded. To downgrade a heroic piece, flip it over. To downgrade a legendary piece, replace it with a heroic piece. If none is available, the legendary piece cannot be downgraded. - Destroy: To destroy a piece, remove it from the board. - Convert: To convert an enemy piece, replace it with one of your pieces of the same rank (unless a different rank is specified). When keeping track of '''how many enemy pieces you destroyed''', count pieces you destroyed during summoning, pieces you destroyed with moves and leaps, pieces you destroyed with a “destroy” effect, and pieces you converted. Neither upgrading nor downgrading ever counts as destroying a piece. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. ---- These rules are extracted from CGE's full rules for Tash-Kalar. 4251cddb1784f1a92e3cc92081462cb992fad993 1805 1804 2016-04-01T13:57:25Z Ernus 12057 /* Resolving effects of beings and flares */ wikitext text/x-wiki == Modalità di gioco == Su Board Game Arena, Tash-Kalar può essere giocato da 2 a 4 giocatori e in 2 distinte modalità: - '''"Forma Suprema":''' I giocatori realizzano punti quando completano un obiettivo corrente e per i pezzi leggendari presenti nell'Arena. Questa modalità è disponibile solo per 2 giocatori. - '''"Duello Mortale"''': Non ci sono obiettivi da completare. I giocatori realizzano punti distruggendo pedine nemiche, evocando creature leggendarie e quando l'avversario invoca una carta impeto. il Duello Mortale può essere giocato da 2 a 4 giocatori. Il gioco in scatola prevede anche modalità a squadra in entrambe le modalità. == Setup == Ogni giocatore inizia con 6 carte pescate a caso: 3 esseri del proprio mazzo, 2 leggendari e 1 impeto. Nella modalità '''"Forma Suprema"''', vengono rivelati 3 obiettivi correnti più 1 come prossimo obiettivo. Nella modalità '''"Duello Mortale"''', il giocatore che gioca per secondo piazza 1 pezzo comune di ogni colore nei quadrati marcati dell'Arena. == Game play == Si comincia dal primo giocatore scelto a caso e si procede in senso orario. Ogni turno prevede 2 azioni, tranne il giocatore iniziale che ha solo 1 azione disponibile come primo turno. Azioni possibili: - '''"Piazzare 1 pezzo semplice"''' del tuo colore su un quadrato vuoto. Se non hai pezzi disponibili devi riprendere 1 dei tuoi pezzi semplici o eroici già piazzati sull'Arena in precedenza e dopo piazzarlo dove vuoi. - '''"Evocare una cretura"'''. Leggi più avanti - '''"Scartare 1 carta creatura del tuo mazzo"'''. Se lo fai puoi anche mettere una o più carte (anche leggendarie o impeti) in fondo al rispettivo mazzo di pesca. Le azioni possono essere eseguite in qualsiasi ordine. Puoi prima "piazzare" e poi "evocare" o viceversa (puoi fare una sola azione di scarto per turno). Devi sempre usare le tue azioni disponibili. Puoi invocare un impeto (leggi più avanti) prima o dopo un'azione. Invocare un impeto non costa nessuna azione. Il tuo turno finisce pescando altrettante carte di quante ne sono state giocate, in modo da avere sempre 3 carte creatura del tuo mazzo, 2 leggendarie e i impeto. Se peschi l'ultima carta del tuo mazzo, potresti finire la partita anche con meno di 3 carte essere in mano. '''"Forma Suprema"''': Alla fine del tuo turno puoi completare solamente 1 dei compiti disponibili, se hai soddisfatto i suoi requisiti. '''"Duello Mortale"''': Alla fine del tuo turno, realizzi punti per le pedine nemiche distrutte: 2 punti per una leggendaria, 1 punto per un'eroica e 1 punto per ogni coppia di pedine semplici distrutte. Nella ''Mischia Mortale'' (3-4 giocatori) fai punti per ogni pedina nemica distrutta nei diversi colori. Il tuo punteggio finale è determinato dal colore nel quale hai il punteggio più basso. Non realizzi punti se distruggi tue pedine e per tutte le pedine semplici nemiche spaiate di un solo colore. Puoi appaiare 2 pedine semplici nemiche di diverso colore e decidere in quale colore realizzare i punti. Realizzi 1 punto (nel colore che preferisci) ogni volta che evochi 1 leggenda (promuovere un pezzo eroico non conta come un'evocazione leggendaria). Se il tuo avversario invoca 1 carta impeto tu guadagni 1 punto. == Evocare una creatura == Per evocare una creatura, usa 1 azione in questo modo: - '''"Gioca una carta"''' dalla tua mano e scegli il quadrato sull'Arena che soddisfi la forma del pattern (disegno) richiesto sulla carta. Il pattern può essere ruotato (a 90, 180 o 270 gradi), specchiato e/o capovolto. I pezzi usati per evocare la creatura devono essere dello stesso grado (o maggiore) riportato sulla carta. I quadrati vuoti non sono essenziali per evocare la creatura. - '''"Piazza un pezzo del grado indicato"''' (in alto a sinistra sulla carta) sul quadrato marcato di bianco nel pattern. Questo quadrato può essere vuoto, a meno che il pattern non specifichi che debba essere occupato da un vostro pezzo. Se il quadrato è occupato da un pezzo dello stesso grado o inferiore, distruggilo, mettendo il nuovo pezzo al suo posto. Se il quadrato è occupato da un pezzo di grado superiore non puoi evocare l'essere in quel quadrato. Se tutti i pezzi di quel tipo sono già piazzati sull'Arena, puoi riprenderne uno di quelli non richiesti dal pattern in questione. - Quando il nuovo pezzo è piazzato sull'Arena '''"risolvi i suoi effetti"''' scritti sulla carta. - Dopo aver risolto gli effetti, scarta la carta. == Invocare un Impeto == Puoi invocare una carta impeto durnte il tuo turno prima o dopo una qualsiasi azione. Per invocare l'impeto devi soddisfare almeno uno dei due criteri scritti sulla carta: - Soddisfi il criterio stampato in alto sulla carta se il tuo avversario ha almeno quel numero di pezzi promossi (eroici e leggendari) più di te nell'Arena. - Soddisfi il criterio stampato in basso sulla carta se il tuo avversario ha almeno quel numero di pezzi totali (semplici, eroici e leggendari) più di te nell'Arena. Se si verificano una o tutte e due condizioni scritte sulla carta puoi risolverne gli effetti. Se soddisfi i criteri contro più avversari scegli contro chi comparare la carta (e quindi assegnare l'eventuale punto nei Duelli Mortali). Una volta che la carta è stata utilizzata bisogna scartarla. == Risolvere gli effetti delle creature e degli Impeti == Nessun'altra azione (anche invocare impeti) può essere intrapresa fino a che l'intero effetto di una carta non sia stato risolto. Alcune parti di un effetto possono essere opzionali: - '''"Puoi"''' indica che una certa parte dell'effetto è opzionale. - '''"Fino a"''' include sempre lo zero. Le parti che non sono specifcate come opzionali sono obbligatorie. Se un effetto non può essere risolto per intero, risolvi solo le parti disponibili. Quando una carta si riferisce al nome della creatura, si riferisce direttamente al pezzo che in quella azione rappresenta la creatura evocata. '''Keywords''': - '''Pezzo promosso:''' un pezzo eroico o leggendario. - '''Pezzo non leggendario:''' Un pezzo comune o eroico. - '''Pezzo:''' Se un pezzo non è specificato se appartiene a te o al tuo avversario, fa riferimento a tutti i pezzi (inclusi i tuoi). - '''Spazio marcato:''' Uno spazio colorato nel pattern. Se il testo della carta non si riferisce al quadrato marcato, i quadrati marcati del pattern sono solo illustrativi. - '''Quadrato adiacente:''' Uno degli otto quadrati adiacenti sia ortogonalmente che diagonalmente ad un determinato pezzo o quadrato. Se il quadrato di riferimento non è specificato, fa riferimento al quadrato occupato dalla nuova creatura evocata. - '''Distanza:''' Il numero di mosse richieste da un quadrato ad un altro. Per esempio, un quadrato adiacente è a distanza 1. - '''Mossa:''' Una mossa è sempre su un quadrato adiacente. Una mossa in un quadrato occupato, distrugge il pezzo presente. - '''Mossa Standard o Normale:''' Questo tipo di mossa può essere fatta solo su quadrati vuoti o su quadrati occupati da pezzi di grado inferiore. - '''Mossa di Combattimento:''' Questo tipo di mossa può essere fatta solo su quadrati vuoti o su quadrati occupati da pezzi di grado uguale o inferiore. - '''Salto normale e Salto di combattimento:''' Un salto è come una mossa con la differenza che il quadrato di destinazione può non essere adiacente. Se non specificato diversamente, il salto può essere fatto su qualsiasi quadrato nell'Arena. - '''Piazza:''' Come l'azione "Piazzare", a differenza che se non ci sono pezzi disponibili di quel colore e grado, il pezzo non può essere piazzato. - '''Promuovi:''' I pezzi leggendari non possono essere promossi. Per promuovere un pezzo comune, giralo. Per promuovere un pezzo eroico rimpiazzalo con uno leggendario. Se i leggendari non sono più disponibili, il pezzo eroico non può essere promosso. - '''Degrada:''' I pezzi comuni non possono essere degradati. Per degradare un pezzo eroico, giralo dal lato comune. Per degradare un pezzo leggendario rimpiazzalo con uno eroico. Se non ci sono pezzi eroici disponibili, il leggendario non può essere degradato. - '''Distruggi:''' Per distruggere un pezzo, rimuovilo dall'Arena. - '''Converti:''' Per convertire un pezzo nemico, rimpiazzalo con uno dei tuoi pezzi dello stesso grado (a meno che non specificato diversamente). Quando bisogna tenere traccia di '''"quanti pezzi nemici hai distrutto"''', conta i pezzi nemici che hai distrutto durante l'evocazione, mosse o salti, pezzi distrutti per "effetti di distruzione" e pezzi convertiti. Nè la promozione nè il degradamento contano come pezzi distrutti. == The end of the game == The end of the game is triggered when a player draws the last card from his or her deck. In '''High Form''', the end of the game is also triggered if a player has 9 or more points at the end of any player’s turn. Count the points for tasks claimed (by the player or by the team) plus 1 point for each legendary piece of that player’s color currently on the board. (It doesn’t matter how the piece became legendary.) In '''Deathmatch''', the end of the game is also triggered if a player reaches or surpasses 18 points. Once the turn that triggers the end is done, play continues so that each player gets one more turn, including the player whose turn triggered the end. Then the game ends. The player with more points wins. If there is a tie, the tiebreakers are, in this order: number of upgraded pieces on the board and then total number of pieces on the board. If there is still a tie, it remains unbroken. ---- These rules are extracted from CGE's full rules for Tash-Kalar. 36ae992dcbdf69044e8092b11be5823dd87dc9d4 1806 1805 2016-04-01T14:05:40Z Ernus 12057 /* The end of the game */ wikitext text/x-wiki == Modalità di gioco == Su Board Game Arena, Tash-Kalar può essere giocato da 2 a 4 giocatori e in 2 distinte modalità: - '''"Forma Suprema":''' I giocatori realizzano punti quando completano un obiettivo corrente e per i pezzi leggendari presenti nell'Arena. Questa modalità è disponibile solo per 2 giocatori. - '''"Duello Mortale"''': Non ci sono obiettivi da completare. I giocatori realizzano punti distruggendo pedine nemiche, evocando creature leggendarie e quando l'avversario invoca una carta impeto. il Duello Mortale può essere giocato da 2 a 4 giocatori. Il gioco in scatola prevede anche modalità a squadra in entrambe le modalità. == Setup == Ogni giocatore inizia con 6 carte pescate a caso: 3 esseri del proprio mazzo, 2 leggendari e 1 impeto. Nella modalità '''"Forma Suprema"''', vengono rivelati 3 obiettivi correnti più 1 come prossimo obiettivo. Nella modalità '''"Duello Mortale"''', il giocatore che gioca per secondo piazza 1 pezzo comune di ogni colore nei quadrati marcati dell'Arena. == Game play == Si comincia dal primo giocatore scelto a caso e si procede in senso orario. Ogni turno prevede 2 azioni, tranne il giocatore iniziale che ha solo 1 azione disponibile come primo turno. Azioni possibili: - '''"Piazzare 1 pezzo semplice"''' del tuo colore su un quadrato vuoto. Se non hai pezzi disponibili devi riprendere 1 dei tuoi pezzi semplici o eroici già piazzati sull'Arena in precedenza e dopo piazzarlo dove vuoi. - '''"Evocare una cretura"'''. Leggi più avanti - '''"Scartare 1 carta creatura del tuo mazzo"'''. Se lo fai puoi anche mettere una o più carte (anche leggendarie o impeti) in fondo al rispettivo mazzo di pesca. Le azioni possono essere eseguite in qualsiasi ordine. Puoi prima "piazzare" e poi "evocare" o viceversa (puoi fare una sola azione di scarto per turno). Devi sempre usare le tue azioni disponibili. Puoi invocare un impeto (leggi più avanti) prima o dopo un'azione. Invocare un impeto non costa nessuna azione. Il tuo turno finisce pescando altrettante carte di quante ne sono state giocate, in modo da avere sempre 3 carte creatura del tuo mazzo, 2 leggendarie e i impeto. Se peschi l'ultima carta del tuo mazzo, potresti finire la partita anche con meno di 3 carte essere in mano. '''"Forma Suprema"''': Alla fine del tuo turno puoi completare solamente 1 dei compiti disponibili, se hai soddisfatto i suoi requisiti. '''"Duello Mortale"''': Alla fine del tuo turno, realizzi punti per le pedine nemiche distrutte: 2 punti per una leggendaria, 1 punto per un'eroica e 1 punto per ogni coppia di pedine semplici distrutte. Nella ''Mischia Mortale'' (3-4 giocatori) fai punti per ogni pedina nemica distrutta nei diversi colori. Il tuo punteggio finale è determinato dal colore nel quale hai il punteggio più basso. Non realizzi punti se distruggi tue pedine e per tutte le pedine semplici nemiche spaiate di un solo colore. Puoi appaiare 2 pedine semplici nemiche di diverso colore e decidere in quale colore realizzare i punti. Realizzi 1 punto (nel colore che preferisci) ogni volta che evochi 1 leggenda (promuovere un pezzo eroico non conta come un'evocazione leggendaria). Se il tuo avversario invoca 1 carta impeto tu guadagni 1 punto. == Evocare una creatura == Per evocare una creatura, usa 1 azione in questo modo: - '''"Gioca una carta"''' dalla tua mano e scegli il quadrato sull'Arena che soddisfi la forma del pattern (disegno) richiesto sulla carta. Il pattern può essere ruotato (a 90, 180 o 270 gradi), specchiato e/o capovolto. I pezzi usati per evocare la creatura devono essere dello stesso grado (o maggiore) riportato sulla carta. I quadrati vuoti non sono essenziali per evocare la creatura. - '''"Piazza un pezzo del grado indicato"''' (in alto a sinistra sulla carta) sul quadrato marcato di bianco nel pattern. Questo quadrato può essere vuoto, a meno che il pattern non specifichi che debba essere occupato da un vostro pezzo. Se il quadrato è occupato da un pezzo dello stesso grado o inferiore, distruggilo, mettendo il nuovo pezzo al suo posto. Se il quadrato è occupato da un pezzo di grado superiore non puoi evocare l'essere in quel quadrato. Se tutti i pezzi di quel tipo sono già piazzati sull'Arena, puoi riprenderne uno di quelli non richiesti dal pattern in questione. - Quando il nuovo pezzo è piazzato sull'Arena '''"risolvi i suoi effetti"''' scritti sulla carta. - Dopo aver risolto gli effetti, scarta la carta. == Invocare un Impeto == Puoi invocare una carta impeto durnte il tuo turno prima o dopo una qualsiasi azione. Per invocare l'impeto devi soddisfare almeno uno dei due criteri scritti sulla carta: - Soddisfi il criterio stampato in alto sulla carta se il tuo avversario ha almeno quel numero di pezzi promossi (eroici e leggendari) più di te nell'Arena. - Soddisfi il criterio stampato in basso sulla carta se il tuo avversario ha almeno quel numero di pezzi totali (semplici, eroici e leggendari) più di te nell'Arena. Se si verificano una o tutte e due condizioni scritte sulla carta puoi risolverne gli effetti. Se soddisfi i criteri contro più avversari scegli contro chi comparare la carta (e quindi assegnare l'eventuale punto nei Duelli Mortali). Una volta che la carta è stata utilizzata bisogna scartarla. == Risolvere gli effetti delle creature e degli Impeti == Nessun'altra azione (anche invocare impeti) può essere intrapresa fino a che l'intero effetto di una carta non sia stato risolto. Alcune parti di un effetto possono essere opzionali: - '''"Puoi"''' indica che una certa parte dell'effetto è opzionale. - '''"Fino a"''' include sempre lo zero. Le parti che non sono specifcate come opzionali sono obbligatorie. Se un effetto non può essere risolto per intero, risolvi solo le parti disponibili. Quando una carta si riferisce al nome della creatura, si riferisce direttamente al pezzo che in quella azione rappresenta la creatura evocata. '''Keywords''': - '''Pezzo promosso:''' un pezzo eroico o leggendario. - '''Pezzo non leggendario:''' Un pezzo comune o eroico. - '''Pezzo:''' Se un pezzo non è specificato se appartiene a te o al tuo avversario, fa riferimento a tutti i pezzi (inclusi i tuoi). - '''Spazio marcato:''' Uno spazio colorato nel pattern. Se il testo della carta non si riferisce al quadrato marcato, i quadrati marcati del pattern sono solo illustrativi. - '''Quadrato adiacente:''' Uno degli otto quadrati adiacenti sia ortogonalmente che diagonalmente ad un determinato pezzo o quadrato. Se il quadrato di riferimento non è specificato, fa riferimento al quadrato occupato dalla nuova creatura evocata. - '''Distanza:''' Il numero di mosse richieste da un quadrato ad un altro. Per esempio, un quadrato adiacente è a distanza 1. - '''Mossa:''' Una mossa è sempre su un quadrato adiacente. Una mossa in un quadrato occupato, distrugge il pezzo presente. - '''Mossa Standard o Normale:''' Questo tipo di mossa può essere fatta solo su quadrati vuoti o su quadrati occupati da pezzi di grado inferiore. - '''Mossa di Combattimento:''' Questo tipo di mossa può essere fatta solo su quadrati vuoti o su quadrati occupati da pezzi di grado uguale o inferiore. - '''Salto normale e Salto di combattimento:''' Un salto è come una mossa con la differenza che il quadrato di destinazione può non essere adiacente. Se non specificato diversamente, il salto può essere fatto su qualsiasi quadrato nell'Arena. - '''Piazza:''' Come l'azione "Piazzare", a differenza che se non ci sono pezzi disponibili di quel colore e grado, il pezzo non può essere piazzato. - '''Promuovi:''' I pezzi leggendari non possono essere promossi. Per promuovere un pezzo comune, giralo. Per promuovere un pezzo eroico rimpiazzalo con uno leggendario. Se i leggendari non sono più disponibili, il pezzo eroico non può essere promosso. - '''Degrada:''' I pezzi comuni non possono essere degradati. Per degradare un pezzo eroico, giralo dal lato comune. Per degradare un pezzo leggendario rimpiazzalo con uno eroico. Se non ci sono pezzi eroici disponibili, il leggendario non può essere degradato. - '''Distruggi:''' Per distruggere un pezzo, rimuovilo dall'Arena. - '''Converti:''' Per convertire un pezzo nemico, rimpiazzalo con uno dei tuoi pezzi dello stesso grado (a meno che non specificato diversamente). Quando bisogna tenere traccia di '''"quanti pezzi nemici hai distrutto"''', conta i pezzi nemici che hai distrutto durante l'evocazione, mosse o salti, pezzi distrutti per "effetti di distruzione" e pezzi convertiti. Nè la promozione nè il degradamento contano come pezzi distrutti. == Fine del Gioco == La fine del gioco è innescata quando un giocatore pesca l'ultima carta dal suo mazzo di creature. Nella modalità '''"Forma Suprema"''', la fine del gioco è innescata anche quando un giocatore raggiunge o supera 9 punti alla fine del suo turno. Conta i punti degli obiettivi completati (dal giocatore o dalla squadra) più 1 punto per ogni pezzo leggendario presente sull'Arena (non importa se sia stato evocato o promosso) Nel '''"Duello Mortale"''', la fine del gioco è innescata anche quando un giocatore raggiunge o supera 18 punti. Quando la fine del gioco è stata innescata, i giocatori giocheranno un solo turno a testa, incluso il giocatore che ha innescato la fine del gioco. Dopo gli ultimi turni il gioco finisce e il giocatore con più punti vince. Se c'è un pareggio, viene risolto in questo modo: - Vince chi ha più pezzi promossi nell'Arena; - In caso di ulteriore pareggio, vince chi ha il numero maggiore di pezzi totali nell'Arena; - In caso di ulteriore pareggio, il gioco è da considerarsi pari. ---- Queste regole sono un estratto del regolamento ufficiale di Tash-Kalar della CGE. 53e3b5e209fbdc888037fa5be8554d9661750749 1807 1806 2016-04-02T20:24:19Z Ernus 12057 /* Evocare una creatura */ wikitext text/x-wiki == Modalità di gioco == Su Board Game Arena, Tash-Kalar può essere giocato da 2 a 4 giocatori e in 2 distinte modalità: - '''"Forma Suprema":''' I giocatori realizzano punti quando completano un obiettivo corrente e per i pezzi leggendari presenti nell'Arena. Questa modalità è disponibile solo per 2 giocatori. - '''"Duello Mortale"''': Non ci sono obiettivi da completare. I giocatori realizzano punti distruggendo pedine nemiche, evocando creature leggendarie e quando l'avversario invoca una carta impeto. il Duello Mortale può essere giocato da 2 a 4 giocatori. Il gioco in scatola prevede anche modalità a squadra in entrambe le modalità. == Setup == Ogni giocatore inizia con 6 carte pescate a caso: 3 esseri del proprio mazzo, 2 leggendari e 1 impeto. Nella modalità '''"Forma Suprema"''', vengono rivelati 3 obiettivi correnti più 1 come prossimo obiettivo. Nella modalità '''"Duello Mortale"''', il giocatore che gioca per secondo piazza 1 pezzo comune di ogni colore nei quadrati marcati dell'Arena. == Game play == Si comincia dal primo giocatore scelto a caso e si procede in senso orario. Ogni turno prevede 2 azioni, tranne il giocatore iniziale che ha solo 1 azione disponibile come primo turno. Azioni possibili: - '''"Piazzare 1 pezzo semplice"''' del tuo colore su un quadrato vuoto. Se non hai pezzi disponibili devi riprendere 1 dei tuoi pezzi semplici o eroici già piazzati sull'Arena in precedenza e dopo piazzarlo dove vuoi. - '''"Evocare una cretura"'''. Leggi più avanti - '''"Scartare 1 carta creatura del tuo mazzo"'''. Se lo fai puoi anche mettere una o più carte (anche leggendarie o impeti) in fondo al rispettivo mazzo di pesca. Le azioni possono essere eseguite in qualsiasi ordine. Puoi prima "piazzare" e poi "evocare" o viceversa (puoi fare una sola azione di scarto per turno). Devi sempre usare le tue azioni disponibili. Puoi invocare un impeto (leggi più avanti) prima o dopo un'azione. Invocare un impeto non costa nessuna azione. Il tuo turno finisce pescando altrettante carte di quante ne sono state giocate, in modo da avere sempre 3 carte creatura del tuo mazzo, 2 leggendarie e i impeto. Se peschi l'ultima carta del tuo mazzo, potresti finire la partita anche con meno di 3 carte essere in mano. '''"Forma Suprema"''': Alla fine del tuo turno puoi completare solamente 1 dei compiti disponibili, se hai soddisfatto i suoi requisiti. '''"Duello Mortale"''': Alla fine del tuo turno, realizzi punti per le pedine nemiche distrutte: 2 punti per una leggendaria, 1 punto per un'eroica e 1 punto per ogni coppia di pedine semplici distrutte. Nella ''Mischia Mortale'' (3-4 giocatori) fai punti per ogni pedina nemica distrutta nei diversi colori. Il tuo punteggio finale è determinato dal colore nel quale hai il punteggio più basso. Non realizzi punti se distruggi tue pedine e per tutte le pedine semplici nemiche spaiate di un solo colore. Puoi appaiare 2 pedine semplici nemiche di diverso colore e decidere in quale colore realizzare i punti. Realizzi 1 punto (nel colore che preferisci) ogni volta che evochi 1 leggenda (promuovere un pezzo eroico non conta come un'evocazione leggendaria). Se il tuo avversario invoca 1 carta impeto tu guadagni 1 punto. == Evocare una creatura == Per evocare una creatura, usa 1 azione in questo modo: - '''"Gioca una carta"''' dalla tua mano e scegli il quadrato sull'Arena che soddisfi la forma del pattern (schema) richiesto sulla carta. Lo schema può essere ruotato (a 90, 180 o 270 gradi), specchiato e/o capovolto. I pezzi usati per evocare la creatura devono essere dello stesso grado (o maggiore) riportato sulla carta. I quadrati vuoti non sono essenziali per evocare la creatura. - '''"Piazza un pezzo del grado indicato"''' (in alto a sinistra sulla carta) sul quadrato marcato di bianco nello schema. Questo quadrato può essere vuoto, a meno che lo schema non specifichi che debba essere occupato da un vostro pezzo. Se il quadrato è occupato da un pezzo dello stesso grado o inferiore, distruggilo, mettendo il nuovo pezzo al suo posto. Se il quadrato è occupato da un pezzo di grado superiore non puoi evocare l'essere in quel quadrato. Se tutti i pezzi di quel tipo sono già piazzati sull'Arena, puoi riprenderne uno di quelli non richiesti dal pattern in questione. - Quando il nuovo pezzo è piazzato sull'Arena '''"risolvi i suoi effetti"''' scritti sulla carta. - Dopo aver risolto gli effetti, scarta la carta. == Invocare un Impeto == Puoi invocare una carta impeto durnte il tuo turno prima o dopo una qualsiasi azione. Per invocare l'impeto devi soddisfare almeno uno dei due criteri scritti sulla carta: - Soddisfi il criterio stampato in alto sulla carta se il tuo avversario ha almeno quel numero di pezzi promossi (eroici e leggendari) più di te nell'Arena. - Soddisfi il criterio stampato in basso sulla carta se il tuo avversario ha almeno quel numero di pezzi totali (semplici, eroici e leggendari) più di te nell'Arena. Se si verificano una o tutte e due condizioni scritte sulla carta puoi risolverne gli effetti. Se soddisfi i criteri contro più avversari scegli contro chi comparare la carta (e quindi assegnare l'eventuale punto nei Duelli Mortali). Una volta che la carta è stata utilizzata bisogna scartarla. == Risolvere gli effetti delle creature e degli Impeti == Nessun'altra azione (anche invocare impeti) può essere intrapresa fino a che l'intero effetto di una carta non sia stato risolto. Alcune parti di un effetto possono essere opzionali: - '''"Puoi"''' indica che una certa parte dell'effetto è opzionale. - '''"Fino a"''' include sempre lo zero. Le parti che non sono specifcate come opzionali sono obbligatorie. Se un effetto non può essere risolto per intero, risolvi solo le parti disponibili. Quando una carta si riferisce al nome della creatura, si riferisce direttamente al pezzo che in quella azione rappresenta la creatura evocata. '''Keywords''': - '''Pezzo promosso:''' un pezzo eroico o leggendario. - '''Pezzo non leggendario:''' Un pezzo comune o eroico. - '''Pezzo:''' Se un pezzo non è specificato se appartiene a te o al tuo avversario, fa riferimento a tutti i pezzi (inclusi i tuoi). - '''Spazio marcato:''' Uno spazio colorato nel pattern. Se il testo della carta non si riferisce al quadrato marcato, i quadrati marcati del pattern sono solo illustrativi. - '''Quadrato adiacente:''' Uno degli otto quadrati adiacenti sia ortogonalmente che diagonalmente ad un determinato pezzo o quadrato. Se il quadrato di riferimento non è specificato, fa riferimento al quadrato occupato dalla nuova creatura evocata. - '''Distanza:''' Il numero di mosse richieste da un quadrato ad un altro. Per esempio, un quadrato adiacente è a distanza 1. - '''Mossa:''' Una mossa è sempre su un quadrato adiacente. Una mossa in un quadrato occupato, distrugge il pezzo presente. - '''Mossa Standard o Normale:''' Questo tipo di mossa può essere fatta solo su quadrati vuoti o su quadrati occupati da pezzi di grado inferiore. - '''Mossa di Combattimento:''' Questo tipo di mossa può essere fatta solo su quadrati vuoti o su quadrati occupati da pezzi di grado uguale o inferiore. - '''Salto normale e Salto di combattimento:''' Un salto è come una mossa con la differenza che il quadrato di destinazione può non essere adiacente. Se non specificato diversamente, il salto può essere fatto su qualsiasi quadrato nell'Arena. - '''Piazza:''' Come l'azione "Piazzare", a differenza che se non ci sono pezzi disponibili di quel colore e grado, il pezzo non può essere piazzato. - '''Promuovi:''' I pezzi leggendari non possono essere promossi. Per promuovere un pezzo comune, giralo. Per promuovere un pezzo eroico rimpiazzalo con uno leggendario. Se i leggendari non sono più disponibili, il pezzo eroico non può essere promosso. - '''Degrada:''' I pezzi comuni non possono essere degradati. Per degradare un pezzo eroico, giralo dal lato comune. Per degradare un pezzo leggendario rimpiazzalo con uno eroico. Se non ci sono pezzi eroici disponibili, il leggendario non può essere degradato. - '''Distruggi:''' Per distruggere un pezzo, rimuovilo dall'Arena. - '''Converti:''' Per convertire un pezzo nemico, rimpiazzalo con uno dei tuoi pezzi dello stesso grado (a meno che non specificato diversamente). Quando bisogna tenere traccia di '''"quanti pezzi nemici hai distrutto"''', conta i pezzi nemici che hai distrutto durante l'evocazione, mosse o salti, pezzi distrutti per "effetti di distruzione" e pezzi convertiti. Nè la promozione nè il degradamento contano come pezzi distrutti. == Fine del Gioco == La fine del gioco è innescata quando un giocatore pesca l'ultima carta dal suo mazzo di creature. Nella modalità '''"Forma Suprema"''', la fine del gioco è innescata anche quando un giocatore raggiunge o supera 9 punti alla fine del suo turno. Conta i punti degli obiettivi completati (dal giocatore o dalla squadra) più 1 punto per ogni pezzo leggendario presente sull'Arena (non importa se sia stato evocato o promosso) Nel '''"Duello Mortale"''', la fine del gioco è innescata anche quando un giocatore raggiunge o supera 18 punti. Quando la fine del gioco è stata innescata, i giocatori giocheranno un solo turno a testa, incluso il giocatore che ha innescato la fine del gioco. Dopo gli ultimi turni il gioco finisce e il giocatore con più punti vince. Se c'è un pareggio, viene risolto in questo modo: - Vince chi ha più pezzi promossi nell'Arena; - In caso di ulteriore pareggio, vince chi ha il numero maggiore di pezzi totali nell'Arena; - In caso di ulteriore pareggio, il gioco è da considerarsi pari. ---- Queste regole sono un estratto del regolamento ufficiale di Tash-Kalar della CGE. 6f1e1302e36164908f931532c971233ceb59a25c 1811 1807 2016-04-16T20:11:56Z Ernus 12057 /* Game play */ wikitext text/x-wiki == Modalità di gioco == Su Board Game Arena, Tash-Kalar può essere giocato da 2 a 4 giocatori e in 2 distinte modalità: - '''"Forma Suprema":''' I giocatori realizzano punti quando completano un obiettivo corrente e per i pezzi leggendari presenti nell'Arena. Questa modalità è disponibile solo per 2 giocatori. - '''"Duello Mortale"''': Non ci sono obiettivi da completare. I giocatori realizzano punti distruggendo pedine nemiche, evocando creature leggendarie e quando l'avversario invoca una carta impeto. il Duello Mortale può essere giocato da 2 a 4 giocatori. Il gioco in scatola prevede anche modalità a squadra in entrambe le modalità. == Setup == Ogni giocatore inizia con 6 carte pescate a caso: 3 esseri del proprio mazzo, 2 leggendari e 1 impeto. Nella modalità '''"Forma Suprema"''', vengono rivelati 3 obiettivi correnti più 1 come prossimo obiettivo. Nella modalità '''"Duello Mortale"''', il giocatore che gioca per secondo piazza 1 pezzo comune di ogni colore nei quadrati marcati dell'Arena. == Game play == Si comincia dal primo giocatore scelto a caso e si procede in senso orario. Ogni turno prevede 2 azioni, tranne il giocatore iniziale che ha solo 1 azione disponibile come primo turno. Azioni possibili: - '''"Piazzare 1 pezzo semplice"''' del tuo colore su un quadrato vuoto. Se non hai pezzi disponibili devi riprendere 1 dei tuoi pezzi semplici o eroici già piazzati sull'Arena in precedenza e dopo piazzarlo dove vuoi. - '''"Evocare una cretura"'''. Leggi più avanti - '''"Scartare 1 carta creatura del tuo mazzo"'''. Se lo fai puoi anche mettere una o più carte (anche leggendarie o impeti) in fondo al rispettivo mazzo di pesca. Le azioni possono essere eseguite in qualsiasi ordine. Puoi prima "piazzare" e poi "evocare" o viceversa (puoi fare una sola azione di scarto per turno). Devi sempre usare le tue azioni disponibili. Puoi invocare un impeto (leggi più avanti) prima o dopo un'azione. Invocare un impeto non costa nessuna azione. Il tuo turno finisce pescando altrettante carte di quante ne sono state giocate, in modo da avere sempre 3 carte creatura del tuo mazzo, 2 leggendarie e 1 impeto. Se peschi l'ultima carta del tuo mazzo, potresti finire la partita anche con meno di 3 carte creatura in mano. '''"Forma Suprema"''': Alla fine del tuo turno puoi completare solamente 1 dei compiti disponibili, se hai soddisfatto i suoi requisiti. '''"Duello Mortale"''': Alla fine del tuo turno, realizzi punti per le pedine nemiche distrutte: 2 punti per una leggendaria, 1 punto per un'eroica e 1 punto per ogni coppia di pedine semplici distrutte. Nella ''Mischia Mortale'' (3-4 giocatori) fai punti per ogni pedina nemica distrutta nei diversi colori. Il tuo punteggio finale è determinato dal colore nel quale hai il punteggio più basso. Non realizzi punti se distruggi tue pedine e per tutte le pedine semplici nemiche spaiate di un solo colore. Puoi appaiare 2 pedine semplici nemiche di diverso colore e decidere in quale colore realizzare i punti. Realizzi 1 punto (nel colore che preferisci) ogni volta che evochi 1 leggenda (promuovere un pezzo eroico non conta come un'evocazione leggendaria). Se il tuo avversario invoca 1 carta impeto tu guadagni 1 punto. == Evocare una creatura == Per evocare una creatura, usa 1 azione in questo modo: - '''"Gioca una carta"''' dalla tua mano e scegli il quadrato sull'Arena che soddisfi la forma del pattern (schema) richiesto sulla carta. Lo schema può essere ruotato (a 90, 180 o 270 gradi), specchiato e/o capovolto. I pezzi usati per evocare la creatura devono essere dello stesso grado (o maggiore) riportato sulla carta. I quadrati vuoti non sono essenziali per evocare la creatura. - '''"Piazza un pezzo del grado indicato"''' (in alto a sinistra sulla carta) sul quadrato marcato di bianco nello schema. Questo quadrato può essere vuoto, a meno che lo schema non specifichi che debba essere occupato da un vostro pezzo. Se il quadrato è occupato da un pezzo dello stesso grado o inferiore, distruggilo, mettendo il nuovo pezzo al suo posto. Se il quadrato è occupato da un pezzo di grado superiore non puoi evocare l'essere in quel quadrato. Se tutti i pezzi di quel tipo sono già piazzati sull'Arena, puoi riprenderne uno di quelli non richiesti dal pattern in questione. - Quando il nuovo pezzo è piazzato sull'Arena '''"risolvi i suoi effetti"''' scritti sulla carta. - Dopo aver risolto gli effetti, scarta la carta. == Invocare un Impeto == Puoi invocare una carta impeto durnte il tuo turno prima o dopo una qualsiasi azione. Per invocare l'impeto devi soddisfare almeno uno dei due criteri scritti sulla carta: - Soddisfi il criterio stampato in alto sulla carta se il tuo avversario ha almeno quel numero di pezzi promossi (eroici e leggendari) più di te nell'Arena. - Soddisfi il criterio stampato in basso sulla carta se il tuo avversario ha almeno quel numero di pezzi totali (semplici, eroici e leggendari) più di te nell'Arena. Se si verificano una o tutte e due condizioni scritte sulla carta puoi risolverne gli effetti. Se soddisfi i criteri contro più avversari scegli contro chi comparare la carta (e quindi assegnare l'eventuale punto nei Duelli Mortali). Una volta che la carta è stata utilizzata bisogna scartarla. == Risolvere gli effetti delle creature e degli Impeti == Nessun'altra azione (anche invocare impeti) può essere intrapresa fino a che l'intero effetto di una carta non sia stato risolto. Alcune parti di un effetto possono essere opzionali: - '''"Puoi"''' indica che una certa parte dell'effetto è opzionale. - '''"Fino a"''' include sempre lo zero. Le parti che non sono specifcate come opzionali sono obbligatorie. Se un effetto non può essere risolto per intero, risolvi solo le parti disponibili. Quando una carta si riferisce al nome della creatura, si riferisce direttamente al pezzo che in quella azione rappresenta la creatura evocata. '''Keywords''': - '''Pezzo promosso:''' un pezzo eroico o leggendario. - '''Pezzo non leggendario:''' Un pezzo comune o eroico. - '''Pezzo:''' Se un pezzo non è specificato se appartiene a te o al tuo avversario, fa riferimento a tutti i pezzi (inclusi i tuoi). - '''Spazio marcato:''' Uno spazio colorato nel pattern. Se il testo della carta non si riferisce al quadrato marcato, i quadrati marcati del pattern sono solo illustrativi. - '''Quadrato adiacente:''' Uno degli otto quadrati adiacenti sia ortogonalmente che diagonalmente ad un determinato pezzo o quadrato. Se il quadrato di riferimento non è specificato, fa riferimento al quadrato occupato dalla nuova creatura evocata. - '''Distanza:''' Il numero di mosse richieste da un quadrato ad un altro. Per esempio, un quadrato adiacente è a distanza 1. - '''Mossa:''' Una mossa è sempre su un quadrato adiacente. Una mossa in un quadrato occupato, distrugge il pezzo presente. - '''Mossa Standard o Normale:''' Questo tipo di mossa può essere fatta solo su quadrati vuoti o su quadrati occupati da pezzi di grado inferiore. - '''Mossa di Combattimento:''' Questo tipo di mossa può essere fatta solo su quadrati vuoti o su quadrati occupati da pezzi di grado uguale o inferiore. - '''Salto normale e Salto di combattimento:''' Un salto è come una mossa con la differenza che il quadrato di destinazione può non essere adiacente. Se non specificato diversamente, il salto può essere fatto su qualsiasi quadrato nell'Arena. - '''Piazza:''' Come l'azione "Piazzare", a differenza che se non ci sono pezzi disponibili di quel colore e grado, il pezzo non può essere piazzato. - '''Promuovi:''' I pezzi leggendari non possono essere promossi. Per promuovere un pezzo comune, giralo. Per promuovere un pezzo eroico rimpiazzalo con uno leggendario. Se i leggendari non sono più disponibili, il pezzo eroico non può essere promosso. - '''Degrada:''' I pezzi comuni non possono essere degradati. Per degradare un pezzo eroico, giralo dal lato comune. Per degradare un pezzo leggendario rimpiazzalo con uno eroico. Se non ci sono pezzi eroici disponibili, il leggendario non può essere degradato. - '''Distruggi:''' Per distruggere un pezzo, rimuovilo dall'Arena. - '''Converti:''' Per convertire un pezzo nemico, rimpiazzalo con uno dei tuoi pezzi dello stesso grado (a meno che non specificato diversamente). Quando bisogna tenere traccia di '''"quanti pezzi nemici hai distrutto"''', conta i pezzi nemici che hai distrutto durante l'evocazione, mosse o salti, pezzi distrutti per "effetti di distruzione" e pezzi convertiti. Nè la promozione nè il degradamento contano come pezzi distrutti. == Fine del Gioco == La fine del gioco è innescata quando un giocatore pesca l'ultima carta dal suo mazzo di creature. Nella modalità '''"Forma Suprema"''', la fine del gioco è innescata anche quando un giocatore raggiunge o supera 9 punti alla fine del suo turno. Conta i punti degli obiettivi completati (dal giocatore o dalla squadra) più 1 punto per ogni pezzo leggendario presente sull'Arena (non importa se sia stato evocato o promosso) Nel '''"Duello Mortale"''', la fine del gioco è innescata anche quando un giocatore raggiunge o supera 18 punti. Quando la fine del gioco è stata innescata, i giocatori giocheranno un solo turno a testa, incluso il giocatore che ha innescato la fine del gioco. Dopo gli ultimi turni il gioco finisce e il giocatore con più punti vince. Se c'è un pareggio, viene risolto in questo modo: - Vince chi ha più pezzi promossi nell'Arena; - In caso di ulteriore pareggio, vince chi ha il numero maggiore di pezzi totali nell'Arena; - In caso di ulteriore pareggio, il gioco è da considerarsi pari. ---- Queste regole sono un estratto del regolamento ufficiale di Tash-Kalar della CGE. bdefad132a3c9a232fea73bca57ac667680b8b0c Gamehelpmetromaniab 0 203 1808 1658 2016-04-08T04:57:01Z Senatorhung 4176 /* THE SCORING PHASE */ wikitext text/x-wiki == DESCRIPTION & OBJECTIVE == Each player represents a subway-building company, and will dig two subway lines across the city. The goal is to connect important destinations - residential areas, commercial areas, and entertainment areas - and to provide them with subway stations. Take advantage of other players lines (for example, stations are built wherever two lines meet ; you can win points at the end by sharing the quickest trip), and try also to deroute or even block off your opponents at the right time, to keep them from well completing their lines! At the end of the game, the city government will run seven "test trips" between designated destinations, placed by the players themselves during the game. For each test trip, the fastest connection between the two points will be rewarded with Public Utility Points, and the player whose subways have the most points wins! == GAME COMPONENTS & SET UP == '''Game Board''' To set up the board, take the four border pieces and put them together. Take the six triangular "city" pieces, and arrange them randomly within the border. '''Counters''' Each player takes a set of counters of a particular color. Each has a score marker (showing a subway train), which is placed on the gameboard on the "0" space of the scoring track. Each player also has counters for two subway lines: one with a solid color, and another with a "striped" color. Each line should have a Start marker (white arrow), an End marker (black arrow), and eighteen triangular Tunnel counters. There are also twelve Destination markers. Each is marked with a letter (A-F), and is paired with another Destination marker. These will be the destinations that will be "tested" after the building phase is complete. The summary of these tests is in the upright corner of the board. Finally, there are thirty "station" markers, which are set by the side of the board, and are not controlled by any player. The map is made up of smaller triangles, which are either blank, have a destination symbol, or a lake/park. Along the edge of the city are white arrows indicating where a subway line starts, and black arrows indicating where they exit the city == THE COURSE OF THE GAME == '''Installation''' Take the destination markers and shuffle them letter-sidedown. With 4 players, each player takes one Residential, one Commercial, and one Entertainment Destination at random. That player then secretly looks at his markers. If two have the same letter, he puts one back and draws a new one until all three have different letters. When all the players have their three Destination markers, they flip them letter-side-up in front of them, visible for others. With 3 players, each player takes one more Destination marker. With 2 players, each player gets 6 Destination markers: one player gets the Destinations A,B,C,D,E,F shown on the left of the gameboard test Summary, the other player uses the ones on the right. '''Player turn''' The most "urbane" player begins. Play goes clockwise starting with the first player. On one's turn, the player MUST do one and only one of the following: - Dig 3 tunnels (to continue one or both of his lines) or - Build an intermediate station (on one of his lines) '''Starting a line''' Each player has two subway lines. On his first turn, a player must, of course, begin a subway line - but only one! A subway line must start from an empty space with a white arrow along the edge of the city. To start a line, place its first tunnel, topped with its "start" marker, in any of these spaces. Then continue normally the line in the city by digging the remaining tunnels. When you will begin your second subway line at any subsequent turn, it must start on one of the "opposite" edges from where your first line began. '''Digging tunnels''' Subway lines are built in the city by placing Tunnels in the triangular spaces. Only one tunnel may be placed in a space, and must conform to the following: - A line must always be built from its terminus; and never "branch off" - A line may not be continued with an acute angle. EXCEPTION: when a line terminates at a station, it may be built out from that station at any angle, even acute. - A line may never make a loop or double back on itself If you choose to dig tunnels on your turn, you MUST place 3 tunnels (unless it is only possible to place fewer). If you have two lines, you may distribute your 3 tunnels between them as you wish. '''Special areas''' The start or end spaces (with an arrow) along the edges of the city can only be used to start or end a line. Tunnel counters may never be placed on the park or the lake. When a player places a tunnel counter on top of a destination area, the player must place immediatly one of his Destination markers on that tunnel piece (of the appropriate type, of course), letter-side up. If a player does not have the appropriate marker, the player may not place that tunnel piece on the destination. Furthermore, each player may only place one destination marker per turn, and two destinations of the same letter cannot touch, either on an angle or on the side. '''Stations''' Most of the stations are created while digging tunnels. A station is immediately placed when: - The line being dug joins another line. In this case, a station is placed where the two lines meet up. - The line, which was running alongside another line, splits off from it. In this case, a station is placed where the line splits off. - When a line, running alongside another line, changes side, NO STATION is placed. The player scores 1 point for each destination area on the board that touches the station. He continues to dig tunnels after placing a station, if he still has some left to build. (i.e., building a station like this does not stop your tunneling.) '''Intermediate stations''' In lieu of digging tunnels, a player may use all his turn to place one station anywhere on one of his lines, between two preexisting stations. A starting or ending marker counts as a station for this purpose. Points are scored as for stations placed while digging tunnels. '''Ending lines''' A line ends on a space with a black arrow. The player digs his last tunnel on that space, topped with an "End Line" counter. A line may not end on the same edge as it started, nor on an adjoining edge to that "start edge," unless all the end spaces on the allowed sides are already taken. When a line ends, that player may immediately place an intermediate station anywhere on the line. However, once a line is completed (with this bonus station), the player may never place an intermediate station on that line again '''End of the building phase''' Players continue building until one of the following occurs: - A player has completed both of his lines - A player places the last station available - Five lines are either completed, or blocked and unable to be completed Note : a line is blocked if it can no longer be extended, typically because all the spaces at its end are already occupied, forbidden, or has run out of tunnels. Then all other players have one last turn to play. After, scoring begins. == THE SCORING PHASE == '''Lines scoring''' First, scores are adjusted as follows: - Players who completed both of their lines lose no station points. - Players who completed only one line lose half their station points (rounded down) - Players who completed none of their lines lose all their station points. Adjust the scoring markers accordingly. '''Test trip scoring''' Each test trip runs between destination markers of the same letter: A to A, then B to B, and so on. You can see the summary of these trips in the upright corner of the board. For each trip, determine the shortest route: - a trip takes 1 minute to go from one station to another (no matter how many tunnel pieces are in between) - and 3 minutes to change from one line to another. A trip may have more than one fastest route. Each player who has a line making up part of the fastest route gets 3 points, plus a bonus of 3 points if he placed one of the destination markers (i.e., if the marker is on a tunnel piece of the player's color). A player may only get points once for each test, even if the player is involved in more than one route. Players who are not involved in the fastest route never get any point. '''Impossible trips''' Sometimes, a test run may be impossible. If that is the case, a city investigation takes place to determine the guilty party or parties: - If the destination marker was never placed on the board, the guilty party is the player who didn't place the marker. - If the marker was placed but nobody put a station touching it, the guilty party is the player who placed the destination. - If the markers were both placed, but no route exists between the two, both players who placed the markers are guilty. The guilty party or parties loose 6 points '''Final test''' The last test run is between the park and the lake. Determine the fastest route, as always. Each player involved in the fastest route gets 5 points. Important note : if your score goes beyond 20 points, move your marker normally, but place one of your tunnels near the 20 to show that. If your score goes below 0 point, place one of your tunnels near the 0. == THE WINNER == At the end of the game, the player with the most points is crowned King of the Subway - i.e., WINS. If there is a tie, the winner is the player who finished the most lines; if there is again a tie, the winner is the player who placed the most tunnels. If there is still a tie, litigation is the only possible solution. == SPECIAL RULES == Two players End of game: 3 lines finished and/or blocked ends the building phase. The other conditions still unchanged. Test trip scoring: the second version of the rules on this topic is not implemented on BGA. Three players End of game: 4 lines finished and/or blocked ends the building phase. The other conditions still unchanged. Test trip scoring: same as with four players. == VARIANTS == Unfair Municipality (3-4 players) Each player keeps his destination markers letter-side-down in front of him. The markers are only revealed when they are placed on a destination area in the city. No Corruption (3-4 players) Ah, everything is straight and clear… Because each player takes pre-etablished destination markers and keeps them in front of him, letter-face-up, of course! 4 players Player 1: A Residential, B Commercial, C Entertainment Player 2: D Residential, A Commercial, E Entertainment Player 3: F Residential, E Commercial, B Entertainment Player 4: C Residential, D Commercial, F Entertainment 3 players : Player 1: A & D Residential, B Commercial, C Entertainment Player 2: C Residential, A & E Commercial, F Entertainment Player 3: F Residential, D Commercial, B & E Entertainment Metromania Official Rulebook, Spiel or Face 6f3d18065ea1dfa954c45c85b682184c1c31d363 Club Board Game Arena 0 8 1809 1637 2016-04-13T12:44:18Z Sourisdudesert 1 wikitext text/x-wiki ==Why can't you just have a standard donation system where I can choose any money amount ?== With this "club" system, we try to highlight players who have supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time. Many websites are using a more classic approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena has chosen to set 3 fixed amounts for donations, in order to rely on a bigger number of small donors. ==Is it mandatory to join the club ?== Of course not. You can play for free with few limitation even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra! You don't need statistics to play and have fun, do you? As a matter of fact, most players are not club members. ==What is a beginner account ? == When you join Board Game Arena, you get a "beginner account" for 30 days. This beginner account allows you to view your own ELO ranking for each game. After 30 days, your account becomes a standard '''non-member''' account. ==What becomes of the money ?== Board Game Arena's service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost). Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)... A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone ! da252be75900da6e066562a7964f646cdbdaedf5 1812 1809 2016-04-21T12:26:20Z Jeg 12085 /* Is it mandatory to join the club ? */ wikitext text/x-wiki ==Why can't you just have a standard donation system where I can choose any money amount ?== With this "club" system, we try to highlight players who have supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time. Many websites are using a more classic approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena has chosen to set 3 fixed amounts for donations, in order to rely on a bigger number of small donors. ==Is it mandatory to join the club ?== Of course not. You can play for free with few limitations even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra! You don't need statistics to play and have fun, do you? As a matter of fact, most players are not club members. ==What is a beginner account ? == When you join Board Game Arena, you get a "beginner account" for 30 days. This beginner account allows you to view your own ELO ranking for each game. After 30 days, your account becomes a standard '''non-member''' account. ==What becomes of the money ?== Board Game Arena's service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost). Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)... A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone ! ac3e7a1f730c5bd05e171fabb5056efdb142a1fd 1813 1812 2016-04-21T12:27:39Z Jeg 12085 /* Why can't you just have a standard donation system where I can choose any money amount ? */ wikitext text/x-wiki ==Why can't you just have a standard donation system where I can choose any amount of money ?== With this "club" system, we try to highlight players who have supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time. Many websites are using a more classic approach with a simple "donation box". By experience, we know that these websites rely on just a few generous users. Board Game Arena has chosen to set 3 fixed amounts for donations, in order to rely on a bigger number of small donors. ==Is it mandatory to join the club ?== Of course not. You can play for free with few limitations even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra! You don't need statistics to play and have fun, do you? As a matter of fact, most players are not club members. ==What is a beginner account ? == When you join Board Game Arena, you get a "beginner account" for 30 days. This beginner account allows you to view your own ELO ranking for each game. After 30 days, your account becomes a standard '''non-member''' account. ==What becomes of the money ?== Board Game Arena's service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost). Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)... A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone ! fc9f7e388bb6d8521fcf0784ea4f9f5115cb0c98 1814 1813 2016-04-21T12:28:19Z Jeg 12085 /* Why can't you just have a standard donation system where I can choose any amount of money ? */ wikitext text/x-wiki ==Why can't you just have a standard donation system where I can choose any amount of money ?== With this "club" system, we try to highlight players who have supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time. Many websites use a more classic approach with a simple "donation box". From experience, we know that these websites rely on just a few generous users. Board Game Arena has chosen to set 3 fixed amounts for donations, in order to rely on a bigger number of small donors. ==Is it mandatory to join the club ?== Of course not. You can play for free with few limitations even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra! You don't need statistics to play and have fun, do you? As a matter of fact, most players are not club members. ==What is a beginner account ? == When you join Board Game Arena, you get a "beginner account" for 30 days. This beginner account allows you to view your own ELO ranking for each game. After 30 days, your account becomes a standard '''non-member''' account. ==What becomes of the money ?== Board Game Arena's service is managed by a semi-professional team who needs money to make it run (in particular: hosting cost). Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)... A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone ! 771c209bfb8c164ba93bcc473e088b13b487d5ac 1815 1814 2016-04-21T12:28:28Z Jeg 12085 /* What becomes of the money ? */ wikitext text/x-wiki ==Why can't you just have a standard donation system where I can choose any amount of money ?== With this "club" system, we try to highlight players who have supported this website recently or do so on a regular basis. Depending on the amount of your donation, you are a member of the club for a given period of time. Many websites use a more classic approach with a simple "donation box". From experience, we know that these websites rely on just a few generous users. Board Game Arena has chosen to set 3 fixed amounts for donations, in order to rely on a bigger number of small donors. ==Is it mandatory to join the club ?== Of course not. You can play for free with few limitations even if you are not a member of the club: Board Game Arena is a free service. Statistics are just an extra! You don't need statistics to play and have fun, do you? As a matter of fact, most players are not club members. ==What is a beginner account ? == When you join Board Game Arena, you get a "beginner account" for 30 days. This beginner account allows you to view your own ELO ranking for each game. After 30 days, your account becomes a standard '''non-member''' account. ==What becomes of the money ?== Board Game Arena's service is managed by a semi-professional team who needs money to make it run (in particular: hosting costs). Player donations are used to develop this website (new features, new games), to make it run (hosting, maintenance), to build the player community (events)... A big "thank you" to all members of the Board Game Arena Club whose contributions allow this website to exist for the enjoyment of everyone ! 733b933e9d4313702acb46f62a380311e890085c Gamehelpnautilus 0 201 1810 1667 2016-04-14T09:43:07Z Senatorhung 4176 wikitext text/x-wiki '''Object of the Game''' During the six rounds of the game, place your divers in order to gain the upper hand in the five great domains that are Science, Exploration, Navigation, Engineering and War. The player who has won in the most domains will be declared the winner at the end of the game. '''Setup''' The gameboard is placed between the two players. The Diver cards are shuffled then placed in a pile at the front of the Nautilus, face down. The special cards are shuffled then placed in a pile at the back of the Nautilus, face down. The Domain cards are shuffled. Five of them are placed faceup on the five empty spaces of the game board. The remaining cards form the draw pile which is placed next to the game board, face down. One of players gets the Nemo token, thus becoming the first player of the round. '''Preparation of the Round''' Before starting a round, each player gets 5 Diver cards, which they look at secretly. Then the first player draws two special cards. After having looked at them, the player keeps one and gives the other to his or her opponent. Some special cards can be played at the beginning of the round and others during the round. '''Round Overview''' To start, the first player places one of their Diver cards face up, along the Nautilus and in front of a Domain card, either on their own side or on the side of their opponent. Then, it's up to that opponent to do the same and so on until the 10 spaces (5 on each side of the Nautilus) have been filled by a card. Some Diver cards have movement arrows: horizontal (#7 and #8) or vertical (#6 and #9). When they are played, these cards MUST cause a movement action, unless there is no possible movement matching the direction of the arrow. At the end of the round, the value of the Diver cards placed face-up, on both sides of the Nautilus, will determine who gets the Domain cards in play. '''End of the Round''' The round ends as soon as all 10 spaces on both sides of the Nautilus have been filled by a card (Diver or special). The Domain cards are then awarded. A player gets a Domain card when the value of the Diver card on their side is higher than that of the one on the opposite side. There is one exception to this rule: the Diver card of value 1 (with a crab on it) always wins against the card of value 14. '''End of Game and Scoring''' The game ends at the end of the 6th round, when the pile of Domain cards is empty. Each player takes the pile of Domain cards won during the game. In each of the 5 domains (Science, Exploration, Navigation, Engineering, War), the players will compare their totals: two stars are worth 2 points, one star is worth 1 point, an ink blot removes 1 point from the concerned domain. The player with the highest points score in a domain wins that domain. The player who wins most domains wins the game. '''Game Option''' "Domain cards" option: - Visible: all collected domain cards by players are visible (by default). - Hidden: collected cards by player are visible and collected cards by opponent are hidden. '''Some Features of This Adaptation of the Game''' Duration of the game is 6 rounds by rules, but in this adaptation the game can proceed less 6 rounds. It can happen when one of players has won 3 of 5 domains at end of one of rounds. Player won the domain at end a round if: 1. He has gained 4 or more score points in the domain (during all previous rounds including current round). OR 2. He has gained 3 score points in the domain and domain card with -1 point(ink blot) already was played off (already in hand of one of players). It was done to end a game and not to play superfluous rounds when one of players already won a game. At end of game each player gets 1 victory point for each domain won (domain won by player when one of two conditions was executed, see above). Total score of a game is number of domains won by each player. 3748033ac60d881f1ca795039713f1956de38902 Faq 0 3 1816 1793 2016-04-24T19:14:42Z Sourisdudesert 1 /* How you guys make money? Do you make a living of it? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from around the world. A selection of various board games and card games are available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible, we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What games are available on BGA?=== Board Game Arena offers a selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games, you can find players at any time of day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, who is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players who have joined the table. If you are the table administrator and can't launch the game, most of the time it's because there are not yet enough players who have joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also start the game manually any time after the minimum number of required players have joined. ===What does the small colored circle next to a player's name mean?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but has not performed any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Players earn more victory points for winning a game that has more players (half a point per player). So: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. For example, a player who plays a three player game and wins a third of the time will have: "50% hits", while a player who plays a four person game and wins a third of the time, will have: "67% hits" == During the game == ===What do the icons next to players' names mean?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and has used up their reflection time. Can someone wake them up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of this fact. If the situation doesn't change, it might suggest that this player has a connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (has left the game or been fired from the game). The game is going on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for their turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as they need to about the next move... well as long as there is still some time left on the game clock, that is. * Then you can ask this player to confirm that he or she is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left the computer temporarily. * If the player is not coming back, you can skip their turn as soon as the clock is negative. This player will get a "leave" penalty and you will win "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give them a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from their profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Since the beginning of 2016, one BGA Founder (Sourisdudesert) is working full-time on BGA. It was really required by the growing audience playing on this website, and this has been made possible thanks to all paying members (thank you again!). But to be honest, there is so much work to do on BGA that a single person is not enough. This is not really an issue because we think the "community based" approach is the best for BGA and we'd like to continue to give you the possibility to contribute to make this service running. === Do you recruit? === If we had enough money we would start by "recruiting ourselves" :) cf5d3b7e16257760c514e476548f2fc47f70495f 1817 1816 2016-04-24T19:15:01Z Sourisdudesert 1 /* Do you recruit? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from around the world. A selection of various board games and card games are available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible, we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What games are available on BGA?=== Board Game Arena offers a selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games, you can find players at any time of day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, who is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players who have joined the table. If you are the table administrator and can't launch the game, most of the time it's because there are not yet enough players who have joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also start the game manually any time after the minimum number of required players have joined. ===What does the small colored circle next to a player's name mean?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but has not performed any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Players earn more victory points for winning a game that has more players (half a point per player). So: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. For example, a player who plays a three player game and wins a third of the time will have: "50% hits", while a player who plays a four person game and wins a third of the time, will have: "67% hits" == During the game == ===What do the icons next to players' names mean?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and has used up their reflection time. Can someone wake them up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of this fact. If the situation doesn't change, it might suggest that this player has a connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (has left the game or been fired from the game). The game is going on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for their turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as they need to about the next move... well as long as there is still some time left on the game clock, that is. * Then you can ask this player to confirm that he or she is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left the computer temporarily. * If the player is not coming back, you can skip their turn as soon as the clock is negative. This player will get a "leave" penalty and you will win "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give them a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from their profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, is BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Since the beginning of 2016, one BGA Founder (Sourisdudesert) is working full-time on BGA. It was really required by the growing audience playing on this website, and this has been made possible thanks to all paying members (thank you again!). But to be honest, there is so much work to do on BGA that a single person is not enough. This is not really an issue because we think the "community based" approach is the best for BGA and we'd like to continue to give you the possibility to contribute to make this service running. 284037a1d88ec5cd4ea3708f22825f82f143a827 1819 1817 2016-04-29T00:50:40Z The tim 8705 /* Why is BGA slow? Why do I have bad connections performances on BGA? */ wikitext text/x-wiki [[Category:Help]] == General questions == ===What is Board Game Arena?=== Board Game Arena (BGA) is an online board game platform. With BGA, you can play online and in real time against players from around the world. A selection of various board games and card games are available. In order to play, the only thing you need is your browser! ===What do you mean by "real time play"?=== On Board Game Arena your opponents are connected to the game platform during the entire game. They can see your moves and react to them immediately - as is the case in the real world. ===What is "turn based play"?=== This is often referred to as "asynchronous play" on other sites, and is used here to differentiate from "real time play". Instead of all players being around the table at the same time, players leave and come back. After your opponent takes a move you are notified that it is your turn (via email or on your next visit to the site). You then go to your game, take your turn, and the process repeats for the next player. For details please read [[Turn based FAQ]]. ===What do I need to play?=== Your browser ... and that's it! Board Game Arena does not require anything else on your computer. Thus, you can play from any computer, anywhere, anytime! In order to make this possible, we are using the latest technologies available for the web. This is the reason you should play with the most up to date web browsers to enjoy an optimal BGA experience (read more about our [[Browser_support|browser policy]]). ===How much does it cost to play on BGA?=== Playing on BGA is free. You can also choose to help us by making a donation and becoming a [http://en.boardgamearena.com/#!club Board Game Arena club] member. ===What games are available on BGA?=== Board Game Arena offers a selection of board and card games, but specializes in modern ("European style") adult games. [http://en.boardgamearena.com/#!gamelist See available games]. == Meeting players and starting games == ===I launched a new table but nobody is joining?=== For the most popular games, you can find players at any time of day. For other games, we advise you to come back at peak hour (around 22:00 CEST) if you can't find opponents at the moment. Tip: check the number of online/available players for a game before launching the table. Tip: if nobody is available for a realtime game, you can turn your table into a turn-based table, so another player can join even hours/days after you created it. ===I joined a game. When does the game start?=== '''For realtime games''': Each table has an administrator, who is the table creator. It is the responsibility of the table administrator to start the game when he or she is satisfied with the number of players who have joined the table. If you are the table administrator and can't launch the game, most of the time it's because there are not yet enough players who have joined the table. '''For turnbased games''': The game starts as soon as the maximum number of players has been reached. The table administrator can also start the game manually any time after the minimum number of required players have joined. ===What does the small colored circle next to a player's name mean?=== * http://fr.boardgamearena.com/theme/img/status/online_.png : this player is active. He or she completed an action very recently. * http://fr.boardgamearena.com/theme/img/status/inactive_.png : this player is inactive. He or she is connected to the website but has not performed any action recently. * http://fr.boardgamearena.com/theme/img/status/offline_.png : this player is offline. ===What does the '% hits' statistic mean?=== % hits = number of victory points / number of games played Players earn more victory points for winning a game that has more players (half a point per player). So: * When you win a 2 players game: 1 point. * When you win a 3 players game: 1.5 points. * When you win a 4 players game: 2 points. * etc. For example, a player who plays a three player game and wins a third of the time will have: "50% hits", while a player who plays a four person game and wins a third of the time, will have: "67% hits" == During the game == ===What do the icons next to players' names mean?=== * http://fr.boardgamearena.com/theme/img/layout/active_player.gif : this player must make a move now. * http://fr.boardgamearena.com/theme/img/layout/active_player_clockalert.gif : this player must make a move now, and has used up their reflection time. Can someone wake them up? ;) * http://fr.boardgamearena.com/theme/img/layout/active_player_nonack.gif : this player must make a move now, but is probably not aware of this fact. If the situation doesn't change, it might suggest that this player has a connection issue. * http://fr.boardgamearena.com/theme/img/common/zombie.png : this player is a "zombie" (has left the game or been fired from the game). The game is going on without this player. When the "normal" avatar of a player is displayed, it means that this player is waiting for their turn to play. ===A player has to make a move but he/she doesn't. What can I do?=== * First, please remember that this player has the right to think as long as they need to about the next move... well as long as there is still some time left on the game clock, that is. * Then you can ask this player to confirm that he or she is still thinking about how to play. * If this player seems to be away, we advise you to wait a few minutes: this player may be experiencing some network problems or have left the computer temporarily. * If the player is not coming back, you can skip their turn as soon as the clock is negative. This player will get a "leave" penalty and you will win "by forfeit". For more details, please read [[Game clock]]. ===What is the current progression of the game I'm playing?=== A percentage of progression is displayed on the top of the web page. There is also a progress bar at the bottom of the web page shows you the current progression of the game. ===What is forbidden on Board Game Arena?=== * Leaving a game in progress on purpose. * Taking an unnecessary and unreasonable amount of time at the end of game in an obvious losing situation. * Kingmaking: enabling another player to win on purpose while there is a better move to make for yourself. * Running out of time on the game clock. * Giving some piece of information about the current game situation that corrupts the normal game flow. * Communicating with another player about the game privately (ex: with MSN). * Provocation / triumphalism / defeatism ... anything which is not fair play. * Having a shocking avatar (no advertisement, no politics, ...) Going against these rules will affect your reputation. ===What is absolutely forbidden in Board Game Arena?=== * Creating multiple accounts and playing against oneself. * Insulting other players in any manner. Going against these rules can lead to the removal of your account and/or to the blacklisting of your IP. ===What if some player does something wrong?=== The Board Game Arena platform has been designed to encourage players to maintain good behavior. The reputation system allows you to distinguish between good and bad players. Then, it is up to you to decide whether to start a game with them or not. If you think a player has behaved badly during a game, you can give them a "red thumb" at the end of the game. If you think a player has committed a serious wrongdoing during a game (ex: insult), please report this player to us, using the "report this player" link from their profile or game result page, so that we can take appropriate measures. == Tournaments == Tournaments is a BETA feature of BGA (for a long time). Tournament management is very complex. We'd like to open tournament creation to everyone at some time in the future but it need a lot of work and until then we always had something more urgent to do. When tournaments will be improved, this FAQ section will be improved too. == About board games we proposed on BGA == ===What is the legal status of this website?=== All the games currently available on this site have been licensed or otherwise authorized by copyright holders. Please be aware that games available on BGA can be removed at the copyright holders demand (for example: if they publish their own adaptation of the game). Board Game Arena would like to thank all game publishers and game designers who allow us to have their games here, thus making it possible for this website to exist. === How do we select games that are on BGA? Why the game XXX is not on BGA? === To have a game published on BGA we need 2 things: * The authorization of the rights owner (most of the time: original publisher of the game). * A software developer who develops the adaptation (ie: has some time available to develop it). We (= BGA team) are trying a lot of board games ourselves. Sometimes we are lucky enough to play prototypes too. And of course we receive a lot of game suggestions through the BGA forum, the BoardGameGeek "most wanted games" list, or by any other means. Based on this we are asking game publishers for authorizations, and sometimes we also receive requests directly from game publishers - there is no rule. As it is today, BGA has a very good reputation and very productive relationships with almost all major board game publishers, but this is not enough: each situation is specific, and there can be various reasons why a game publisher can refuse to see a game adaptation on BGA (for example: board games with a third party licence, like "Star Wars", is practically impossible to negotiate). On the other hand, we got some authorizations for some very good games but no developers volunteering to develop them, or sometimes some of them don't manage to finish the job. Developers of adaptations are volunteers, and we don't blame them for this. Finally, some games are authorized and being developed, but the time frame is not good. For example, it happened that we had too many games to release and we decided to delay some of them. It also frequently happens that we must synchronize the release of a game with a publisher event, so the game adaptation can stay "on hold" for some months. So if you are asking yourself: why game XXX is not on BGA, it could be for various reasons: * Maybe we never asked authorization for this game. Note that usually we ask authorizations for every popular games (ex: "Most wanted games"). So if the game is popular, the reason is probably not this one. * The publisher refused. * The publisher accepted, but we didn't find a developer until now for this game. * The game adaptation is ready, but we are waiting for a specific event to release it. To conclude: yes we are taking into account your suggestions, but as you can see there are many factors than can influence the fact that a game is (or is not) on BGA. In addition, as a rule of thumb, we don't communicate about "why" this game is not on BGA. If we already got the authorization, we want to keep the "surprise", and if we didn't get the authorization, the game publisher may not want to explain the reasons. === Are you taking into account the "Most wanted games" list? When will these games be on BGA? === You should read first the previous section ("how do we select games that are on BGA?"). So the answer is: * Yes, we are taking this list into account. * For most of these games we already asked for authorizations. * Some of these games won't be on BGA (authorization refused), some may be, some are in an "intermediate" step. * We don't communicate about future game releases anyway. === Why do some games have expansions on BGA and some don't? === You should read first the previous section ("how do we select games that are on BGA?"). Game expansions follow the same steps than games. There can be various reasons why a game publisher doesn't want the expansion online, and sometimes we don't find a developer that has the time to develop it. ===I'm a game publisher: why would I like to have my game on Board Game Arena?=== The main goal of Board Game Arena is to make it easy for people to discover and love new games. We think that there are only two kinds of players on Board Game Arena: those who already bought the games they are playing online, and those who plan to buy them soon! As the activity of this website contributes to increasing a game's popularity and thus generates hard copy sales in the "real world", we think it is beneficial to the board game community: people from all over the world can play online, we can have fun developing this game platform to the best of our ability, and game publishers get money from the box sales and build a special relationship with their player's community. === I'm a game publisher: how to get my game on Board Game Arena === At first, you just have to write us an email (contact (at) boardgamearena.com) with a description of your game(s). Then, we add this game to the list of "available licences" on our website dedicated to game developers ([http://studio.boardgamearena.com BGA Studio]). The most difficult part is to find a developer among our community. Our only requirement is that the developer must love the game. Of course, the most popular the game is, the easiest it is to find a volunteer developer. Sometimes it is very fast, sometimes it takes months, sometimes it never happens. We can't say in advance. It is also possible to find your own developer: of course it accelerates the process a lot! == Turn-based mode == Please read [[Turn based FAQ]]. == Issues with BGA == ===What can I do if I have an issue with the website?=== Most of the issues on this website should be solved with a simple web page refresh (or "F5"). If you experience persistent issues, you can browse the [http://boardgamearena.com/#!bugs bug tool], see if someone already reported the issue, and add a new bug report if that's not the case. Please take some time to describe the bug you are reporting in detail so that we can quickly reproduce and fix it. === Why is my bug still not fixed? === We fix bugs every weeks. Of course we have priorities: * We give the highest priority to recent features and recent games, because the most important bugs are reported fast. * We give the highest priority to the bugs with the biggest number of "green thumb" on the [http://boardgamearena.com/#!bugs bug tool]. * Usually we fix bugs by group. So if we decide to fix an important bug on a game, there is a chance that we will fix 3 or 4 minor bugs at the same time. BGA is known for the quality of its adaptations, and if you look at the bug tool, you can see that -considering the number of games and the size of the community- there are not so many critical bugs with a lot of "green thumbs". Please also note that BGA adaptations are realized by volunteers (even if most of them are also professional developers). It is not always easy for them to fix bugs, especially when some players are complaining violently and/or do not give precise information in bug reports. === I played on smartphone / tablet / touch device and I have some difficulties: what can I do? === As a rule of thumb, BGA does not support tablets/smartphones. There are tons of board game adaptations for tablets/smartphones, and some BGA adaptations are not well designed for small screens. Thus, we don't have plans to do a mobile / tablet version at the moment. So if you want to use BGA from a smartphone / tablet you can, but we don't promise to fix all bugs so it's at your own risk :) === Why is BGA slow? Why do I have bad connections performances on BGA? === We are constantly monitoring server responsiveness. Some incidents occurs, but most of the time BGA is responsive. We designed our game servers (ie: servers used when you are inside a game) to be very responsive. Usually, less than 2% of the game moves take more than 200 milliseconds to process, and less than 0.2% take more than 1 second. BGA servers are located in Europe (France), but we bought servers all across the world (19 locations) so that the big files (ex: images) are loaded fast even if you are far from us. Most of bad performances came from your internet connection or your system. Try to connect with a different browser / computer / internet connection to troubleshoot the issue. As a rule of thumb, if BGA is not responsive enough, you shouldn't engage yourself into a game because there is a risk for you to get clock penalties. === I got issue with a specific player: how does the moderation works? === You should read [[Moderation and grades]] page. == Contribute to BGA == === How can I contribute to BGA? === Please visit page [http://boardgamearena.com/#!contribute Contribute to BGA]. === I'm a software developer. What can I do? === We created a website specifically dedicated to board games adaptation development: [http://studio.boardgamearena.com BGA Studio]. == About the BGA team == === Who are you? How to contact you? === Please read page [[About us]]. === How you guys make money? Do you make a living of it? === Since the beginning of 2016, one BGA Founder (Sourisdudesert) is working full-time on BGA. It was really required by the growing audience playing on this website, and this has been made possible thanks to all paying members (thank you again!). But to be honest, there is so much work to do on BGA that a single person is not enough. This is not really an issue because we think the "community based" approach is the best for BGA and we'd like to continue to give you the possibility to contribute to make this service running. f94298fee28135400365179f722c412cb8d1a3b4 Steps to create a BGA game 0 117 1818 1106 2016-04-24T23:33:27Z Tackster 12246 spelling error wikitext text/x-wiki Here's a summary of the different steps you would follow when developing a game with BGA Studio. {| class="wikitable" |- ! Step !! How to reach this ste?p !! What happened during the step? |- | Initial || [[How to join BGA developer team?]] || You can choose to join an existing team / create a new project |- | Assigned || You choose a game || You can start the development of the game |- | Pre-alpha || You've started to write some piece of code || You develop the game. During this phase, we can assist you with the framework and give you some pieces of advice. |- | Alpha || You tell us that your development is finished || "BGA review": we are reviewing your game and check if it respects [http://fr.slideshare.net/boardgamearena/bga-studio-guidelines BGA guidelines]. If not, we will ask you (and help you) to fix them. |- | Private beta || We give a "go" || "Publisher review": On preproduction platform, the publisher, the designer, we and you can test the game together and separately. We help you to take into account remarks from the publisher and the designer. |- | Public beta || The adaptation is approved by the publisher || We find together a good launch date for the game, we announce the game on BGA news, and then player can start to play! During the first days, it is common that some bugs are reported by players, and you can fix them following the instructions in [[Post-release phase]]. |- | Gold || The game is stable on BGA || Congrats! You can still modify and optimize things following the instructions in [[Post-release phase]]. |} 7d9a63f0ae6df3bd654f9916556e646b5d42c220 Gamehelpseasons 0 43 1820 1480 2016-04-29T19:06:00Z Orcbobsledteam 12024 Added additional details and clarified some points. wikitext text/x-wiki In Seasons, you take on the role of a wizard competing for the most prestige in the Tournament of Seasons. Gameplay involves choosing the correct combination of dice and the drafting/activation of card powers. There are two kinds of resources in the game: Energy tokens (which come in the four elements), and crystals (which translate directly to points at the end of the game, and are also used as a currency for some things during the game.) The game begins with a draft in which each player selects a total of nine cards. Players divide these cards into three groups of three. The first group will start in your hand. The second and third groups are added to your hand at the start of the second and third game year, respectively. Your final score calculated by adding the prestige points on your cards in play to your crystal total. Five points are deducted for each power card remaining in your hand. The player with the most points wins. ===Dice Selection=== At the start of each round, dice appropriate to the current are rolled. Each player selects one in turn order. The effects are as follows: *''Star'' - Increase your summoning gauge, i.e. the maximum number of cards you can have in play. (Capped at 15.) *''Elements'' - Gain an energy token of the element shown (water, earth, air, or fire). *''Numbers'' - Gain the number of crystals indicated. *''Card outline'' - Draw a card. You will have the option of keeping or discarding the card. *''Circle surrounding the die symbols'' - You may transmute energy tokens into crystals. The rate depends on the current season. *''Pips'' - The number of pips on the die that is not selected by the players determine how many months the time marker will advance. Each die will have some combination of these symbols. For example, a dice may give you a water, earth and allow you to transmute, all in the same turn. ===Power Cards=== All cards in the game are referred to collectively as Power Cards. There are two types: Familiars (orange border) and Magic Items (purple border). Cards can have the following effects: *''Ongoing'' - The described effect persists indefinitely. Denoted by a circular arrow. *''When Played'' - The effect occurs once when the card enters play. *''When Activated'' - The card must be activated (and any relevant cost paid) to produce the listed effect. Cards may be activated once each round. ===The Seasons=== The board is divided into four seasons each of which have common, uncommon and rare elements. These designations tell you how likely it is that these elements will appear during each season and also tell you how much each element will transmute into during that season. *'''Winter''' (Blue) - Water and Wind are Common, Fire is Uncommon, and Earth is Rare. *'''Spring''' (Green) - Earth and Water are Common, Wind is Uncommon, and Fire is Rare. *'''Summer''' (Yellow) - Fire and Earth are Common, Water is Uncommon, and Wind is Rare. *'''Fall''' (Red) - Wind and Fire are Common, Earth is Uncommon, and Water is Rare. Example: During Spring, Earth and Water are the most common and will transmute into one crystal each, Wind is uncommon and will transmute into two crystals each, and Fire is rare and will transmute into three crystals each. ===Bonuses=== Up to three times per game, you may use one of the following abilities, referred to as a "Bonus": *Convert two energy tokens into other elements. *Gain the ability to transmute this turn, and gain one additional crystal per energy transmuted. *Increase your summoning gauge by one. *If your Seasons die shows the "Draw a card" icon, you may instead draw two and select one to keep. The first bonus you use deducts five points at game end, the second costs seven, and the third costs eight. ===Additional Rules=== By default, your reserve may have seven energy tokens. If you acquire more tokens than you can hold, you must immediately discard the excess. If a card allows you to summon another card but you have no space for this second card, it will be discarded with no refund. Notes on card terminology: *''Sacrifice'' - Put one of your cards in play into the discard pile. *''Discard'' - Put one of the cards in your hand into the discard pile. ==Difficulty Levels== '''Apprentice wizard level''' In order to make the game easier to learn, there are “pre-constructed” sets of nine power cards. Instead of taking step 1 of the first game phase, each player gets one of these sets. '''Magician level''' Only the power cards numbered 1 to 30 are in play. These cards have easy to grasp effects and will allow you to slowly discover the world of Seasons. '''Archmage level''' All 50 kinds of power cards are in play. The cards numbered 31 through 50 have more complex effects than the basic cards, but will allow you to extend the fun of playing by discovering new effects and combinations. 3cec13f93faf466a8be8d0366055d190ac4c7c50 1848 1820 2016-06-01T01:33:50Z Joesondow 13512 Added missing word wikitext text/x-wiki In Seasons, you take on the role of a wizard competing for the most prestige in the Tournament of Seasons. Gameplay involves choosing the correct combination of dice and the drafting/activation of card powers. There are two kinds of resources in the game: Energy tokens (which come in the four elements), and crystals (which translate directly to points at the end of the game, and are also used as a currency for some things during the game.) The game begins with a draft in which each player selects a total of nine cards. Players divide these cards into three groups of three. The first group will start in your hand. The second and third groups are added to your hand at the start of the second and third game year, respectively. Your final score calculated by adding the prestige points on your cards in play to your crystal total. Five points are deducted for each power card remaining in your hand. The player with the most points wins. ===Dice Selection=== At the start of each round, dice appropriate to the current season are rolled. Each player selects one in turn order. The effects are as follows: *''Star'' - Increase your summoning gauge, i.e. the maximum number of cards you can have in play. (Capped at 15.) *''Elements'' - Gain an energy token of the element shown (water, earth, air, or fire). *''Numbers'' - Gain the number of crystals indicated. *''Card outline'' - Draw a card. You will have the option of keeping or discarding the card. *''Circle surrounding the die symbols'' - You may transmute energy tokens into crystals. The rate depends on the current season. *''Pips'' - The number of pips on the die that is not selected by the players determine how many months the time marker will advance. Each die will have some combination of these symbols. For example, a dice may give you a water, earth and allow you to transmute, all in the same turn. ===Power Cards=== All cards in the game are referred to collectively as Power Cards. There are two types: Familiars (orange border) and Magic Items (purple border). Cards can have the following effects: *''Ongoing'' - The described effect persists indefinitely. Denoted by a circular arrow. *''When Played'' - The effect occurs once when the card enters play. *''When Activated'' - The card must be activated (and any relevant cost paid) to produce the listed effect. Cards may be activated once each round. ===The Seasons=== The board is divided into four seasons each of which have common, uncommon and rare elements. These designations tell you how likely it is that these elements will appear during each season and also tell you how much each element will transmute into during that season. *'''Winter''' (Blue) - Water and Wind are Common, Fire is Uncommon, and Earth is Rare. *'''Spring''' (Green) - Earth and Water are Common, Wind is Uncommon, and Fire is Rare. *'''Summer''' (Yellow) - Fire and Earth are Common, Water is Uncommon, and Wind is Rare. *'''Fall''' (Red) - Wind and Fire are Common, Earth is Uncommon, and Water is Rare. Example: During Spring, Earth and Water are the most common and will transmute into one crystal each, Wind is uncommon and will transmute into two crystals each, and Fire is rare and will transmute into three crystals each. ===Bonuses=== Up to three times per game, you may use one of the following abilities, referred to as a "Bonus": *Convert two energy tokens into other elements. *Gain the ability to transmute this turn, and gain one additional crystal per energy transmuted. *Increase your summoning gauge by one. *If your Seasons die shows the "Draw a card" icon, you may instead draw two and select one to keep. The first bonus you use deducts five points at game end, the second costs seven, and the third costs eight. ===Additional Rules=== By default, your reserve may have seven energy tokens. If you acquire more tokens than you can hold, you must immediately discard the excess. If a card allows you to summon another card but you have no space for this second card, it will be discarded with no refund. Notes on card terminology: *''Sacrifice'' - Put one of your cards in play into the discard pile. *''Discard'' - Put one of the cards in your hand into the discard pile. ==Difficulty Levels== '''Apprentice wizard level''' In order to make the game easier to learn, there are “pre-constructed” sets of nine power cards. Instead of taking step 1 of the first game phase, each player gets one of these sets. '''Magician level''' Only the power cards numbered 1 to 30 are in play. These cards have easy to grasp effects and will allow you to slowly discover the world of Seasons. '''Archmage level''' All 50 kinds of power cards are in play. The cards numbered 31 through 50 have more complex effects than the basic cards, but will allow you to extend the fun of playing by discovering new effects and combinations. 5e0907a627c58986a4c7d0e3352f86a06ca0b8ff 1849 1848 2016-06-01T01:36:41Z Joesondow 13512 Grammar fix wikitext text/x-wiki In Seasons, you take on the role of a wizard competing for the most prestige in the Tournament of Seasons. Gameplay involves choosing the correct combination of dice and the drafting/activation of card powers. There are two kinds of resources in the game: Energy tokens (which come in the four elements), and crystals (which translate directly to points at the end of the game, and are also used as a currency for some things during the game.) The game begins with a draft in which each player selects a total of nine cards. Players divide these cards into three groups of three. The first group will start in your hand. The second and third groups are added to your hand at the start of the second and third game year, respectively. Your final score calculated by adding the prestige points on your cards in play to your crystal total. Five points are deducted for each power card remaining in your hand. The player with the most points wins. ===Dice Selection=== At the start of each round, dice appropriate to the current season are rolled. Each player selects one in turn order. The effects are as follows: *''Star'' - Increase your summoning gauge, i.e. the maximum number of cards you can have in play. (Capped at 15.) *''Elements'' - Gain an energy token of the element shown (water, earth, air, or fire). *''Numbers'' - Gain the number of crystals indicated. *''Card outline'' - Draw a card. You will have the option of keeping or discarding the card. *''Circle surrounding the die symbols'' - You may transmute energy tokens into crystals. The rate depends on the current season. *''Pips'' - The number of pips on the die that is not selected by the players determine how many months the time marker will advance. Each die will have some combination of these symbols. For example, a die may give you a water, earth and allow you to transmute, all in the same turn. ===Power Cards=== All cards in the game are referred to collectively as Power Cards. There are two types: Familiars (orange border) and Magic Items (purple border). Cards can have the following effects: *''Ongoing'' - The described effect persists indefinitely. Denoted by a circular arrow. *''When Played'' - The effect occurs once when the card enters play. *''When Activated'' - The card must be activated (and any relevant cost paid) to produce the listed effect. Cards may be activated once each round. ===The Seasons=== The board is divided into four seasons each of which have common, uncommon and rare elements. These designations tell you how likely it is that these elements will appear during each season and also tell you how much each element will transmute into during that season. *'''Winter''' (Blue) - Water and Wind are Common, Fire is Uncommon, and Earth is Rare. *'''Spring''' (Green) - Earth and Water are Common, Wind is Uncommon, and Fire is Rare. *'''Summer''' (Yellow) - Fire and Earth are Common, Water is Uncommon, and Wind is Rare. *'''Fall''' (Red) - Wind and Fire are Common, Earth is Uncommon, and Water is Rare. Example: During Spring, Earth and Water are the most common and will transmute into one crystal each, Wind is uncommon and will transmute into two crystals each, and Fire is rare and will transmute into three crystals each. ===Bonuses=== Up to three times per game, you may use one of the following abilities, referred to as a "Bonus": *Convert two energy tokens into other elements. *Gain the ability to transmute this turn, and gain one additional crystal per energy transmuted. *Increase your summoning gauge by one. *If your Seasons die shows the "Draw a card" icon, you may instead draw two and select one to keep. The first bonus you use deducts five points at game end, the second costs seven, and the third costs eight. ===Additional Rules=== By default, your reserve may have seven energy tokens. If you acquire more tokens than you can hold, you must immediately discard the excess. If a card allows you to summon another card but you have no space for this second card, it will be discarded with no refund. Notes on card terminology: *''Sacrifice'' - Put one of your cards in play into the discard pile. *''Discard'' - Put one of the cards in your hand into the discard pile. ==Difficulty Levels== '''Apprentice wizard level''' In order to make the game easier to learn, there are “pre-constructed” sets of nine power cards. Instead of taking step 1 of the first game phase, each player gets one of these sets. '''Magician level''' Only the power cards numbered 1 to 30 are in play. These cards have easy to grasp effects and will allow you to slowly discover the world of Seasons. '''Archmage level''' All 50 kinds of power cards are in play. The cards numbered 31 through 50 have more complex effects than the basic cards, but will allow you to extend the fun of playing by discovering new effects and combinations. e29bcebc6c956a034d826341677e3348ab54e393 Implijer:Fmoros 2 216 1821 2016-05-03T13:00:00Z Fmoros 13074 Created page with "Expat living in South Korea. Loving board games since I was a kid. Have a big collection of children games, old vintage games and some strategy games, too." wikitext text/x-wiki Expat living in South Korea. Loving board games since I was a kid. Have a big collection of children games, old vintage games and some strategy games, too. 5cac3508314f3a57faf5202f93d4d1c713235c76 Tutorial reversi 0 57 1822 1753 2016-05-04T02:24:05Z Victoria la 11989 Added missing instructions on putting tokens graphics in img wikitext text/x-wiki == Introduction == Using this tutorial, you can build a complete working game on the BGA environment: Reversi. Before you read this tutorial, you must: * Read the overall presentations of the BGA Framework ([[Studio|see here]]). * Know the [http://en.wikipedia.org/wiki/Reversi#Rules rules of Reversi]. * Know the languages used on BGA: PHP, SQL, HTML, CSS, Javascript. == Create your first game == With the initial skeleton of code provided initially, you can already start a game from the BGA Studio. For now, we are going to work with 1 player only. Most of the time this is simpler to proceed with only one player during the early phase of development of your game, as it's easy and fast to start/stop games. Thus, you can start a "Reversi" game, and arrive on a void, empty game. Yeah. == Let it look like Reversi == It's always a good idea to start with a little bit of graphic work. Why? Because this helps to figure out how the final game will be, and issues that may appear later. Be careful designing the layout of your game: you must always keep in mind that players with a 1024px screen width must be able to play. Usually, it means that the width of the play area can be 750px (in the worst case). For Reversi, it's useless to have a 750x750px board - much too big, so we choose this one which fit perfectly (536x528): [[File:Board.jpg]] Note that we are using a jpg file. Jpg are lighter than png, so faster to load. Later we are going to use PNGs for discs for transparency purpose. Now, let's make it appears on our game: * upload board.jpg in your "img/" directory. * edit "reversi_reversi.tpl" to add a 'div' for your board: <pre> <div id="board"> </div> </pre> * edit your reversi.css file to transform it into a visible board: #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); } Refresh your page. Here's your board: [[File:reversi1.jpg]] == Make the squares appears == Now, what we need is to create some invisible HTML elements where squares are. These elements will be used as position references for white and black discs. Obviously, we need 64 squares. To avoid writing 64 'div' elements on our template, we are going to use the "block" feature. Let's modify our template like this: <pre> <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> </div> </pre> As you can see, we created a "square" block, with 4 variable elements: X, Y, LEFT and TOP. Obviously, we are going to use this block 64 times during page load. Let's do it in our "reversi.view.php" file: <pre> $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Note: as you can see, squares in our "board.jpg" files does not have an exact width/height in pixel, and that's the reason we are using floating point numbers here. Now, to finish our work and check if everything works fine, we are going to style our square a little bit in our CSS stylesheet: <pre> #board { width: 536px; height: 528px; background-image: url('img/board.jpg'); position: relative; } .square { width: 62px; height: 62px; position: absolute; background-color: red; } </pre> Explanations: * With "position: relative" on board, we ensure square elements are positioned relatively to board. * For the test, we use a red background color for the square. This is a useful tip to figure out if everything is fine with invisible elements. Let's refresh and check our our (beautiful) squares: [[File:reversi2.jpg]] == The discs == Now, our board is ready to receive some disc tokens! At first, we introduce a new 'div' element as a child of "board" to host all these tokens (in our template): <pre> <!-- END square --> <div id="tokens"> </div> </div> </pre> Then, let's introduce a new piece of art with the discs. We need some transparency here so we are using a png file: [[File:tokens.png]] Upload this image file "tokens.png" in your "img/" directory. Important: we are using ONE file for both discs. It's really important that you use a minimum number of graphic files for your game with this "CSS sprite" technique, because it makes the game loading faster and more reliable. [http://www.w3schools.com/css/css_image_sprites.asp Read more about CSS sprites]. Now, let's separate the disc with some CSS stuff: <pre> .token { width: 56px; height: 56px; position: absolute; background-image: url('img/tokens.png'); } .tokencolor_ffffff { background-position: 0px 0px; } .tokencolor_000000 { background-position: -56px 0px; } </pre> With this CSS code, we apply the classes "token" and "tokencolor_ffffff" to a div element and we've got a white token. Yeah. Note the "position: absolute" which allows us to position tokens on the board and make them "slide" to their positions. Now, let's make a first token appear on our board. Disc tokens are not visible at the beginning of the game: they appear dynamically during the game. For this reason, we are going to make them appear from our Javascript code, with a BGA Framework technique called "JS template". In our template file (reversi_reversi.tpl), let's create the piece of HTML needed to display our token: <pre> <script type="text/javascript"> // Templates var jstpl_token='<div class="token tokencolor_${color}" id="token_${x_y}"></div>'; </script> </pre> Note: we already created the "templates" section for you in the game skeleton. As you can see, we defined a JS template named "jstpl_token" with a piece of HTML and two variables: the color of the token and its x/y coordinates. Note that the syntax of the argument is different for template block variables (brackets) and JS template variables (dollar and brackets). Now, let's create a method in our Javascript code that will make a token appear on the board, using this template: <pre> addTokenOnBoard: function( x, y, player ) { dojo.place( this.format_block( 'jstpl_token', { x_y: x+'_'+y, color: this.gamedatas.players[ player ].color } ) , 'tokens' ); this.placeOnObject( 'token_'+x+'_'+y, 'overall_player_board_'+player ); this.slideToObject( 'token_'+x+'_'+y, 'square_'+x+'_'+y ).play(); }, </pre> At first, with "dojo.place" and "this.format_block" methods, we create a HTML piece of code and insert it as a new child of "tokens" div element. Then, with BGA "this.placeOnObject" method, we place this element over the panel of some player. Immediately after, using BGA "this.slideToObject" method, we make the disc slide to the "square" element, its final destination. Note: don't forget to call the "play()", otherwise the token remains at its original location. Note: note that during all the process, the parent of the new disc HTML element will remain "tokens". placeOnObject and slideToObject methods are only moving the position of elements on screen, and they are not modifying the HTML tree. Before we can show a token, we need to set the player colors in the setupNewGame function in reversi.game.php: <pre> $default_colors = array( "ffffff", "000000" ); </pre> Now, to test if everything works fine, just add "this.addTokenOnBoard( 2, 2, [player_id] )" in the "setup" Javascript method in reversi.js, and reload the page. A token should appear and slide immediately to its position, like this: [[File:reversi3.jpg]] == The database == We did most of the client-side programming, so let's have a look on the other side now. To design the database model of our game, the best thing to do is to follow the "Go to game database" link at the bottom of our game, to access the database directly with a [http://www.phpmyadmin.net/ PhpMyAdmin] instance. Then, you can create the tables you need for your table (do not remove existing tables!), and report every SQL command used in your "dbmodel.sql" file. [[File:reversi4.jpg]] The database model of Reversi is very simple: just one table with the squares of the board. In our dbmodel.sql, we have this: <pre> CREATE TABLE IF NOT EXISTS `board` ( `board_x` smallint(5) unsigned NOT NULL, `board_y` smallint(5) unsigned NOT NULL, `board_player` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`board_x`,`board_y`) ) ENGINE=InnoDB; </pre> Now, a new database with a "board" table will be created each time we start a Reversi game. This is why after modifying our dbmodel.sql it's a good time to stop & start again our game. == Setup the initial game position == The "setupNewGame" method of our reversi.game.php is called during initial setup: this is the place to initialize our data and to place the initial tokens on the board (initially, there are 4 tokens on the board). Let's do this: <pre> // Init the board $sql = "INSERT INTO board (board_x,board_y,board_player) VALUES "; $sql_values = array(); list( $blackplayer_id, $whiteplayer_id ) = array_keys( $players ); for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $token_value = "NULL"; if( ($x==4 && $y==4) || ($x==5 && $y==5) ) // Initial positions of white player $token_value = "'$whiteplayer_id'"; else if( ($x==4 && $y==5) || ($x==5 && $y==4) ) // Initial positions of black player $token_value = "'$blackplayer_id'"; $sql_values[] = "('$x','$y',$token_value)"; } } $sql .= implode( $sql_values, ',' ); self::DbQuery( $sql ); // Active first player self::activeNextPlayer(); </pre> As you can see, we create one table entry for each square, with a "NULL" value which means "empty square". Of course, for 4 specific squares, we place an initial token. At the end, we call activeNextPlayer to make the first player active at the beginning of the game. Now, we need to make these tokens appear on the client side. To achieve this, the first step is to return the token positions with our "getAllDatas" PHP method (called during each page reload): <pre> // Get reversi board token $result['board'] = self::getObjectListFromDB( "SELECT board_x x, board_y y, board_player player FROM board WHERE board_player IS NOT NULL" ); </pre> As you can see, we are using the BGA framework "getObjectListFromDB" method that formats the result of this SQL query in a PHP array with x, y and player attributes. The last thing we need to do is to process this array client side, and place a disc token on the board for each array item. Of course, we are doing this is our Javascript "setup" method: <pre> for( var i in gamedatas.board ) { var square = gamedatas.board[i]; if( square.player !== null ) { this.addTokenOnBoard( square.x, square.y, square.player ); } } </pre> As you can see, our "board" entry created in "getAllDatas" can be used here as "gamedatas.board" in our Javascript. We are using our previously developed "addTokenOnBoard" method. Reload... and here we are: [[File:reversi5.jpg]] It starts to smell Reversi here... == The game state machine == Now, let's stop our game again, because we are going to start the core game logic. You already read the "Focus on BGA game state machine", so you know that this is the heart of your game logic. For reversi, it's very simple although. Here's a diagram of our game state machine: [[File:reversi6.jpg]] And here's our "states.inc.php", according to this diagram: <pre> $machinestates = array( 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 10 ) ), 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), 11 => array( "name" => "nextPlayer", "type" => "game", "action" => "stNextPlayer", "updateGameProgression" => true, "transitions" => array( "nextTurn" => 10, "cantPlay" => 11, "endGame" => 99 ) ), 99 => array( "name" => "gameEnd", "description" => clienttranslate("End of game"), "type" => "manager", "action" => "stGameEnd", "args" => "argGameEnd" ) ); </pre> Now, let's create in reversi.game.php the methods that are declared in this game states description file: * argPlayerTurn * stNextPlayer ... and start a new Reversi game. As you can see on the screen capture below, the BGA framework makes the game jump to our first game state "playerTurn" right after the initial setup. That's why the status bar contains the description of playerTurn state ("XXXX must play a disc"): [[File:reversi7.jpg]] == The rules == Now, what we would like to do is to indicate to the current player where she is allowed to play. The idea is to build a "getPossibleMoves" PHP method that return a list of coordinates where she is allowed to play. This method will be used in particular: * As we just said, to help the player to see where she can play. * When the player plays, to check if she has the right to play here. This is pure PHP programming here, and there are no special things from the BGA framework that can be used. This is why we won't go into details here. The overall idea is: * Create a "getTurnedOverDiscs(x,y)" method that return coordinates of discs that would be turned over if a token would be played at x,y. * Loop through all free squares of the board, call the "getTurnedOverDiscs" method on each of them. If at least 1 token is turned over, this is a valid move. One important thing to keep in mind is the following: making a database query is slow, so please don't load the entire game board with a SQL query multiple time. In our implementation, we load the entire board once at the beginning of "getPossibleMoves", and then pass the board as an argument to all methods. If you want to look into details, please look at the "utility method" sections of reversi.game.php. == Display allowed moves == Now, what we want to do is highlight the squares where the player can place a disc. To do this, we are using the "argPlayerTurn" method. This method is called each time we enter into "playerTurn" game state, and its result is transfered automatically to the client-side: <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves( self::getActivePlayerId() ) ); } </pre> We are of course using the "getPossibleMoves" method we just developed. Now, let's go to the client side to use the data returned by the method above. We are using the "onEnteringState" Javascript method that is called each time we enter into a new game state: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> So, when we are entering into "playerTurn" game state, we are calling our "updatePossibleMoves" method. This method looks like this: <pre> updatePossibleMoves: function( possibleMoves ) { // Remove current possible moves dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); for( var x in possibleMoves ) { for( var y in possibleMoves[ x ] ) { // x,y is a possible move dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); } } this.addTooltipToClass( 'possibleMove', '', _('Place a disc here') ); }, </pre> The idea here is that we've created a CSS class ("possibleMove") that can be applied to a "square" element to highlight it: <pre> .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } </pre> At first, we remove all "possibleMove" classes currently applied with the very useful combination of "dojo.query" and "removeClass" method. Then we loop through all possible moves our PHP "updatePossibleMoves" function created for us, and add the "possibleMove" class to each corresponding square. Finally, we use the BGA framework "addTooltipToClass" method to associate a tooltip to all those highlighted squares so that players can understand their meaning. And here we are: [[File:reversi8.jpg.jpg]] == Let's play == From now, it's better to restart a game with 2 players, because we are going to implement a complete Reversi turn. The summary of what we are going to do is: * When we click on a "possibleMove" square, send the move to the server. * Server side, check the move is correct, apply Reversi rules and jump to next player. * Client side, change the disc position to reflect the move. Thus, what we do first is associate each click on a square to one of our method. We are doing this in our Javascript "setup" method: <pre> dojo.query( '.square' ).connect( 'onclick', this, 'onPlayDisc' ); </pre> Note the use of the "dojo.query" method to get all HTML elements with "square" class in just one function call. Now, our "onPlayDisc" method is called each time someone clicks on a square. Here's our "onPlayDisc" method below: <pre> onPlayDisc: function( evt ) { // Stop this event propagation dojo.stopEvent( evt ); // Get the cliqued square x and y // Note: square id format is "square_X_Y" var coords = evt.currentTarget.id.split('_'); var x = coords[1]; var y = coords[2]; if( ! dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { // This is not a possible move => the click does nothing return ; } if( this.checkAction( 'playDisc' ) ) // Check that this action is possible at this moment { this.ajaxcall( "/reversi/reversi/playDisc.html", { x:x, y:y }, this, function( result ) {} ); } }, </pre> What we do here is: * We stop the propagation of the Javascript "onclick" event. Otherwise, it can lead to random behavior so it's always a good idea. * We get the x/y coordinates of the square by using "evt.currentTarget.id". * We check that clicked square has the "possibleMove" class, otherwise we know for sure that we can't play there. * We check that "playDisc" action is possible, according to current game state (see "possibleactions" entry in our "playerTurn" game state defined above). This check is important to avoid issues if a player double clicks on a square. * Finally, we make a call to the server using BGA "ajaxcall" method with argument x and y. Now, we have to manage this "playDisc" action on the server side. At first, we introduce a "playDisc" entry point in our "reversi.action.php": <pre> public function playDisc() { self::setAjaxMode(); $x = self::getArg( "x", AT_posint, true ); $y = self::getArg( "y", AT_posint, true ); $result = $this->game->playDisc( $x, $y ); self::ajaxResponse( ); } </pre> As you can see, we get the 2 arguments x and y from the javascript call, and call a corresponding "playDisc" method in our game logic. Now, let's have a look of this playDisc method: <pre> function playDisc( $x, $y ) { // Check that this player is active and that this action is possible at this moment self::checkAction( 'playDisc' ); </pre> ... at first, we check that this action is possible according to current game state (see "possible action"). We already did it on client side, but it's important to do it on server side too (otherwise it would be possible to cheat). <pre> // Now, check if this is a possible move $board = self::getBoard(); $player_id = self::getActivePlayerId(); $turnedOverDiscs = self::getTurnedOverDiscs( $x, $y, $player_id, $board ); if( count( $turnedOverDiscs ) > 0 ) { // This move is possible! </pre> ...now, we are using the "getTurnedOverDiscs" method again to check that this move is possible. <pre> // Let's place a disc at x,y and return all "$returned" discs to the active player $sql = "UPDATE board SET board_player='$player_id' WHERE ( board_x, board_y) IN ( "; foreach( $turnedOverDiscs as $turnedOver ) { $sql .= "('".$turnedOver['x']."','".$turnedOver['y']."'),"; } $sql .= "('$x','$y') ) "; self::DbQuery( $sql ); </pre> ... we update the database to change the color of all turned over disc + the disc we just placed. <pre> // Update scores according to the number of disc on board $sql = "UPDATE player SET player_score = ( SELECT COUNT( board_x ) FROM board WHERE board_player=player_id )"; self::DbQuery( $sql ); // Statistics self::incStat( count( $turnedOverDiscs ), "turnedOver", $player_id ); if( ($x==1 && $y==1) || ($x==8 && $y==1) || ($x==1 && $y==8) || ($x==8 && $y==8) ) self::incStat( 1, 'discPlayedOnCorner', $player_id ); else if( $x==1 || $x==8 || $y==1 || $y==8 ) self::incStat( 1, 'discPlayedOnBorder', $player_id ); else if( $x>=3 && $x<=6 && $y>=3 && $y<=6 ) self::incStat( 1, 'discPlayedOnCenter', $player_id ); </pre> ... now, we update both player score by counting all disc, and we manage game statistics. <pre> // Notify self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); self::notifyAllPlayers( "turnOverDiscs", '', array( 'player_id' => $player_id, 'turnedOver' => $turnedOverDiscs ) ); $newScores = self::getCollectionFromDb( "SELECT player_id, player_score FROM player", true ); self::notifyAllPlayers( "newScores", "", array( "scores" => $newScores ) ); </pre> ... then we notify about all these changes. We are using for that 3 notifications ('playDisc', 'turnOverDiscs' and 'newScores' that we are going to implement on client side later). Note that the description of the 'playDisc' notification will be logged in the game log. <pre> // Then, go to the next state $this->gamestate->nextState( 'playDisc' ); } else throw new feException( "Impossible move" ); } </pre> ... finally, we jump to the next game state if everything goes fine ('playDisc' is also the name of a transition in the 'playerTurn' game state description above). To make the statistics work, we have to initialize them in stats.inc.php: <pre> // Statistics existing for each player "player" => array( "discPlayedOnCorner" => array( "id"=> 10, "name" => totranslate("Discs played on a corner"), "type" => "int" ), "discPlayedOnBorder" => array( "id"=> 11, "name" => totranslate("Discs played on a border"), "type" => "int" ), "discPlayedOnCenter" => array( "id"=> 12, "name" => totranslate("Discs played on board center part"), "type" => "int" ), "turnedOver" => array( "id"=> 13, "name" => totranslate("Number of discs turned over"), "type" => "int" ) ) </pre> A last thing to do on the server side is to activate the next player when we enter the "nextPlayer" game state: <pre> function stNextPlayer() { // Activate next player $player_id = self::activeNextPlayer(); self::giveExtraTime( $player_id ); $this->gamestate->nextState( 'nextTurn' ); } </pre> Now, when we play a disc, the rules are checked and the disc appears in the database. [[File:reversi9.jpg]] Of course, as we don't manage notifications on client side, we need to press F5 after each move to see the changes on the board. == Make the move appear automatically == Now, what we have to do is process the notifications sent by the server and make the move appear on the interface. In our "setupNotifications" method, we register 2 methods for the 2 notifications we created at the previous step ('playDisc' and 'turnOverDiscs'): <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); dojo.subscribe( 'turnOverDiscs', this, "notif_turnOverDiscs" ); this.notifqueue.setSynchronous( 'turnOverDiscs', 1500 ); </pre> As you can see, we associate our 2 notifications with 2 methods with the "notif_" prefix. At the same time, we define these notifications as "synchronous", with a duration in millisecond (500 for the first one, and 1500 for the second one). It tells the user interface to wait some time after executing the notification, to let the animation end before starting the next notification. In our specific case, the animation will be the following: * Make a disc slide from the player panel to its place on the board * (wait 500ms) * Make all turned over discs blink (and of course turned them over) * (wait 1500ms) * Let the next player play. Let's have a look now on the "playDisc" notification handler method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addTokenOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> No surprise here, we re-used some existing stuff to: * Remove the highlighted squares. * Add a new disc on board, coming from player panel. Now, here's the method that handles the turnOverDiscs notification: <pre> notif_turnOverDiscs: function( notif ) { // Get the color of the player who is returning the discs var targetColor = this.gamedatas.players[ notif.args.player_id ].color; // Make these discs blink and set them to the specified color for( var i in notif.args.turnedOver ) { var token = notif.args.turnedOver[ i ]; // Make the token blink 2 times var anim = dojo.fx.chain( [ dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ), dojo.fadeOut( { node: 'token_'+token.x+'_'+token.y, onEnd: function( node ) { // Remove any color class dojo.removeClass( node, [ 'tokencolor_000000', 'tokencolor_ffffff' ] ); // ... and add the good one dojo.addClass( node, 'tokencolor_'+targetColor ); } } ), dojo.fadeIn( { node: 'token_'+token.x+'_'+token.y } ) ] ); // end of dojo.fx.chain // ... and launch the animation anim.play(); } }, </pre> The list of the discs to be turned over has been made available by our server side code in "notif.args.turnedOver" (see previous paragraph). We loop through all these discs, and create a complex animation using dojo.Animation for each of them. The complete documentation on dojo animations [http://dojotoolkit.org/documentation/tutorials/1.6/animation/ can be found here]. In few words: we create a chain of 4 animations to make the disc fade out, fade in, fade out again, and fade in again. At the end of the second fade out, we change the color of the disc. Finally, we launch the animation with "play()". 6a4e695141232e5d3c8c874e7662b4c6718862df Gamehelpaknile 0 217 1823 2016-05-10T13:48:25Z Rockerrullz 4211 1st draft of the rules wikitext text/x-wiki == '''Nile - The game of ancient agriculture by Daniel Callister''' == Steps in each turn: <br /><br /> 1 - ''Flood'' <br /> 2 - ''Harvest'' <br /> 3 - ''Trade'' <br /> 4 - ''Plant Or Speculate'' <br /> 5 - ''Draw'' <br /><br /> 1) '''Flood''' The top-most card in the draw deck is turned face up and placed on top of the Flood card. This card determines what fields will harvest and what cards may not be played this turn.<br /> Speculation cards are also resolved during this step. 2) '''Harvest''' What crops may be harvested are based on the current Flood card. Each time a new Flood card is turned over, any Player who has that crop currently planted (regardless of whose turn it is) removes the top card in that crop’s field and places it face down into their individual storage pile. Your storage pile is a collection of all of your harvested crops. Besides serving as your score and determinging the winner, it may be inventoried and traded from throughout the game. Keep the contents of your storage pile secret from the other players! If the Flood card is a Speculation card, it will show multiple crops. When this happens, all shown crops are harvested. If the Plague of Locusts card is drawn as the Flood card, it is immediately resolved and discarded. A new card is then drawn in its place to serve as the Flood card. 3) '''Trade''' Trading allows you to discard two old cards in order to receive a single new card. There are two options for trading: ''Market'' - Discard any two cards (Crop and/or Speculation) from your hand and/or storage pile and draw one card from the draw pile. Add this to your hand. ''Offering to Hapi'' - Discard any two cards (Crop and/or Speculation) from your hand and/or storage pile and replace the current Flood card with a new one from the top of the draw pile. This new Flood card acts as any other Flood card, thus causing a new Harvest and preventing certain cards from being played. Continue as if it’s Step 2) Harvest again.Players need not trade at all during their turn. Players may trade using both options in any order, any number of times per turn. All cards traded away are discarded. Players may not trade with each other, nor can planted cards be traded. 4) '''Plant Or Speculate''' The Plant or Speculate step is regulated by the Flood card. Any cards showing crop types that are currently flooded may not be played during this step. ''Plant'' – To plant you must place crops from your hand face up in front of you, forming a field. While a field of a given crop type is in play, no one else may create a field using the same crop. As such, there are never more fields in play than there are crops at any time. When planting a new field, players may: Plant at least two cards of all the same crop type. Plant exactly two cards of differing crops (one of which may be planted into an existing field). Plant any number of crops to any number of fields that already exist in front of you. A player may not plant a new field if another player currently has a field of that crop type in front of them, unless the new field will contain more cards than the existing field. When this happens, all cards in the other player’s field of that crop type must be discarded immediately. ''Speculate'' – Instead of planting, the active player may play one or two Speculation cards. These are cards with two crop types represented on them. When successful, a Speculation card allows that player to immediately draw three (3) cards into their hand. As with planting, Speculation cards showing crops currently flooded may not be played. To play Speculation cards, simply place them face-up in your play area. Speculation cards are successful when they have at least one crop type in common with the next Flood card revealed. The game pauses and the player who played the Speculation card(s) immediately draws three (one card matched) or six (both cards matched) cards into their hand from the draw pile. All speculation cards (successful and not) are then discarded and the game continues. 5) '''Draw''' To end a turn, the active player draws the top two (2) cards from the draw pile and adds them to their hand. Once the active player has drawn their cards, their turn is over. The next player moving clockwise starts their turn as the active player. When the draw pile is exhausted, reshuffle the Flood stack, the Plague card, and all discarded cards to create a new draw pile. ---- '''''Plague of Locusts''''' When the Plague of Locusts card is drawn it must be announced immediately. The player who drew the card sets it aside face up. Determine among all players who currently has the most cards in any one field. This field is consumed by the plague of locusts and must be completely discarded. If there is a tie, all cards from the tied fields are discarded. If the Plague is drawn as the Flood card, resolve the Plague, then flip over another card to replace it. If you are drawing cards, finish doing so. The Plague card does not count as one of the drawn cards. '''End of the game''' Play through the draw pile a number of times equal to the number of players (i.e. twice with two players, three times with three players, etc.). Once the final draw pile is exhausted, the game ends. Use the Seasons cards included with the game to help you mark how many times you have progressed through the deck. '''Scoring''' Individually, players separate the cards in their storage piles by crop type and then line them up in five piles from left to right, starting with the crop type of which they had the least cards (even if it’s zero) and ending with the crop type of which they had the most. Players then start comparing their piles. Whichever player has the most cards in their left-most pile (the crop type with the least cards) is the winner. If there is a tie, the tied players compare their next pile and so on. In the event of an exact tie for all five piles... play again! ---- Text extracted from the original rules by Daniel Callister 14c7eb3ef120262f5edf2fbc3e52c4bc1ca96f72 1826 1823 2016-05-19T14:16:53Z Rockerrullz 4211 /* Nile - The game of ancient agriculture by Daniel Callister */ wikitext text/x-wiki == '''Steps in each turn''' == 1 - ''Flood'' <br /> 2 - ''Harvest'' <br /> 3 - ''Trade'' <br /> 4 - ''Plant Or Speculate'' <br /> 5 - ''Draw'' <br /> == '''Flood''' == The top-most card in the draw deck is turned face up and placed on top of the Flood card. This card determines what fields will harvest and what cards may not be played this turn.<br /> Speculation cards are also resolved during this step. == '''Harvest''' == What crops may be harvested are based on the current Flood card. Each time a new Flood card is turned over, any Player who has that crop currently planted (regardless of whose turn it is) removes the top card in that crop’s field and places it face down into their individual storage pile. Your storage pile is a collection of all of your harvested crops. Besides serving as your score and determinging the winner, it may be inventoried and traded from throughout the game. Keep the contents of your storage pile secret from the other players! If the Flood card is a Speculation card, it will show multiple crops. When this happens, all shown crops are harvested. If the Plague of Locusts card is drawn as the Flood card, it is immediately resolved and discarded. A new card is then drawn in its place to serve as the Flood card. == '''Trade''' == Trading allows you to discard two old cards in order to receive a single new card. There are two options for trading: ''Market'' - Discard any two cards (Crop and/or Speculation) from your hand and/or storage pile and draw one card from the draw pile. Add this to your hand. ''Offering to Hapi'' - Discard any two cards (Crop and/or Speculation) from your hand and/or storage pile and replace the current Flood card with a new one from the top of the draw pile. This new Flood card acts as any other Flood card, thus causing a new Harvest and preventing certain cards from being played. Continue as if it’s Step 2) Harvest again.Players need not trade at all during their turn. Players may trade using both options in any order, any number of times per turn. All cards traded away are discarded. Players may not trade with each other, nor can planted cards be traded. == '''Plant Or Speculate''' == The Plant or Speculate step is regulated by the Flood card. Any cards showing crop types that are currently flooded may not be played during this step. ''Plant'' – To plant you must place crops from your hand face up in front of you, forming a field. While a field of a given crop type is in play, no one else may create a field using the same crop. As such, there are never more fields in play than there are crops at any time. When planting a new field, players may: Plant at least two cards of all the same crop type. Plant exactly two cards of differing crops (one of which may be planted into an existing field). Plant any number of crops to any number of fields that already exist in front of you. A player may not plant a new field if another player currently has a field of that crop type in front of them, unless the new field will contain more cards than the existing field. When this happens, all cards in the other player’s field of that crop type must be discarded immediately. ''Speculate'' – Instead of planting, the active player may play one or two Speculation cards. These are cards with two crop types represented on them. When successful, a Speculation card allows that player to immediately draw three (3) cards into their hand. As with planting, Speculation cards showing crops currently flooded may not be played. To play Speculation cards, simply place them face-up in your play area. Speculation cards are successful when they have at least one crop type in common with the next Flood card revealed. The game pauses and the player who played the Speculation card(s) immediately draws three (one card matched) or six (both cards matched) cards into their hand from the draw pile. All speculation cards (successful and not) are then discarded and the game continues. == '''Draw''' == To end a turn, the active player draws the top two (2) cards from the draw pile and adds them to their hand. Once the active player has drawn their cards, their turn is over. The next player moving clockwise starts their turn as the active player. When the draw pile is exhausted, reshuffle the Flood stack, the Plague card, and all discarded cards to create a new draw pile. == '''Plague of Locusts''' == When the Plague of Locusts card is drawn it must be announced immediately. The player who drew the card sets it aside face up. Determine among all players who currently has the most cards in any one field. This field is consumed by the plague of locusts and must be completely discarded. If there is a tie, all cards from the tied fields are discarded. If the Plague is drawn as the Flood card, resolve the Plague, then flip over another card to replace it. If you are drawing cards, finish doing so. The Plague card does not count as one of the drawn cards. == '''End of the game''' == Play through the draw pile a number of times equal to the number of players (i.e. twice with two players, three times with three players, etc.). Once the final draw pile is exhausted, the game ends. Use the Seasons cards included with the game to help you mark how many times you have progressed through the deck. == '''Scoring''' == Individually, players separate the cards in their storage piles by crop type and then line them up in five piles from left to right, starting with the crop type of which they had the least cards (even if it’s zero) and ending with the crop type of which they had the most. Players then start comparing their piles. Whichever player has the most cards in their left-most pile (the crop type with the least cards) is the winner. If there is a tie, the tied players compare their next pile and so on. In the event of an exact tie for all five piles... play again! ---- Text extracted from the original rules by Daniel Callister 9ce2bc748ee619699f1c49759b77f93e5c895e4b Gamehelpthroughtheages 0 168 1824 1744 2016-05-14T21:47:02Z Xerethshura 11883 wikitext text/x-wiki During your turn, you may spend your '''actions points''' to: * pick cards from the card rows (if you have room in your hand) ** Wonders cost an additional civil action for each wonder you have finished * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * build/upgrade military units '''Yellow counters''' represent your population. They can be in one of three places: * on the cards on your tableau * on your available worker pool * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in three places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce food or resources * on your wonder, marking how far along it's construction is Building up your civilisation: * '''Food''' lets you move workers from your yellow bank to your available worker pool. * '''Resources''' let you move workers from your available worker pool to a card on your tableau. * '''Science''' (light bulbs) lets you move cards from your hand to your tableau. * When your population grows, you will need to produce more '''happiness''' or your workers will stop working. * Producing '''culture''' will earn you victory points. * Producing more '''military strength''' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars In the ''Simple'' and ''Advanced'' versions, the game ends immediately when there are no more cards to replenish the deck and both players have played an equal number of turns. In the Advanced and Complete games, '''additional points are scored at the end of the game''' according to special event cards. But at the end of the Simple game, additional points are scored the same way every game: * 2 culture scored per 1 Strength (military) * 2 culture scored per Happy Face * 2 culture scored per level 1 technology in play * 1 culture scored per food or resource production per turn * 1 culture scored per 1 Science Rating (science gained per turn) 961413551acd5c0f5dd2bcd7e63153888c7a0cb0 1825 1824 2016-05-14T21:52:09Z Xerethshura 11883 wikitext text/x-wiki During your turn, you may spend your '''actions points''' to: * pick cards from the card rows (if you have room in your hand) ** Wonders cost an additional civil action for each wonder you have finished * play cards to your tableau * increase your population * build/upgrade farms, mines, or urban buildings * build/upgrade military units ** Play tactics cards to increase your military strength. As long as all units contributing to the tactics card are within one age of the card, you get the greater of the two values. '''Yellow counters''' represent your population. They can be in one of three places: * on the cards on your tableau * on your available worker pool * on your "yellow bank" -- when this is empty, you can no longer increase your available population '''Blue counters''' represent food or resources. They can be in three places: * on your farms or mines * on your "blue bank" -- when this is empty, you can no longer produce food or resources * on your wonder, marking how far along it's construction is Building up your civilisation: * '''Food''' lets you move workers from your yellow bank to your available worker pool. * '''Resources''' let you move workers from your available worker pool to a card on your tableau. * '''Science''' (light bulbs) lets you move cards from your hand to your tableau. * When your population grows, you will need to produce more '''happiness''' or your workers will stop working. * Producing '''culture''' will earn you victory points. * Producing more '''military strength''' will protect you from raids or wars. There are 3 versions of ''Through the Ages'': * ''Simple'' plays through Age I * ''Advanced'' plays through Age II, and introduces political actions (colonies and raids), unhappiness, and corruption * ''Complete'' plays through Age III, and introduces wars In the ''Simple'' and ''Advanced'' versions, the game ends immediately when there are no more cards to replenish the deck and both players have played an equal number of turns. In the Advanced and Complete games, '''additional points are scored at the end of the game''' according to special event cards. But at the end of the Simple game, additional points are scored the same way every game: * 2 culture scored per 1 Strength (military) * 2 culture scored per Happy Face * 2 culture scored per level 1 technology in play * 1 culture scored per food or resource production per turn * 1 culture scored per 1 Science Rating (science gained per turn) 8db8b972c3262ac592d120bdc2c65426d94343a0 Gamehelplogger 0 212 1827 1776 2016-05-19T21:33:50Z Een 3 wikitext text/x-wiki From the official rules: [http://www.icehousegames.org/wiki/index.php?title=Logger] == '''Background''' == Four rival lumberjacks are competing to chop down the most trees for their business. However, standing in their way are tree-hugging hippies protesting the deforestation. == '''Glossary''' == The following terms are used in Logger: '''Tree''' - Any seedling, sapling or mature tree on the board. '''Seedling''' - A large pyramid '''Sapling''' - A large pyramid with a medium pyramid stacked on it '''Mature Tree''' - A stack of pyramids. From top to bottom: small, medium, large. '''Protester''' - Denoted by a volcano cap '''Logger''' - A piece representing the player. Denoted by a medium pyramid of a color not used for trees. Non-Icehouse pieces like meeples may be also used. == '''Setup''' == Place a seedling on the center of the board. The remaining pyramid pieces from the Rainbow stash are kept aside in a common pool. Starting with the first player, each player places his logger on a corner of the board. Each player also starts with 1 protester in his or her supply (2 protesters for a 2-player game). Remember who went first as this will be important at the end game. == '''Goal''' == The winner is the player with the most points at the end of the game. Though scoring 10 points triggers the end game, having 10 points may not be enough for victory. == '''Gameplay''' == No Diagonals - Diagonals do not exist in Logger. Any rule pertaining to adjacency or movement is orthogonal only. Each player's turn consists of three parts: Movement, Growth and Action. Movement - Move your logger up to two spaces. Loggers may not occupy or walk through spaces occupied by trees or other loggers. Growth - All trees in the same row and column your logger occupies grow 1 stage. All seedlings become saplings and all saplings become mature trees. Mature trees produce 1 seedling in any space adjacent to them if able. Please note growth of all trees is considered simultaneous, so no tree should experience two stages of growth in one turn, nor should any seedlings newly spawned from a mature tree this turn. All trees in your logger's row and column must grow or create a new seedling if able. Action - There are three options in the Action phase: Plant, Protest and Chop. You must perform an action if able. This phase is skipped if your logger is unable to perform any action. Plant - Plant one seedling in any space adjacent to your logger. Protest - You may place one or more protesters from your supply onto mature trees. Protested trees may not be directly chopped down by any player. Chop - Chop down an unprotested mature tree adjacent to your logger by removing it from the board. Chopping will create a domino effect. Any mature tree behind the first chopped tree will also be considered chopped and so on regardless if they have protesters on them not. This process stops when either the edge of the board or a space occupied by anything other than a mature tree is reached. Score 1 point for each tree removed in this way. Add any protesters from felled trees to your supply. For example, a given row can have this formation: Player-Mature Tree-Mature Tree-Sapling-Mature Tree. When the player chops the first tree, the second one will be removed as well. However, the domino effect ends at the sapling because it is not fully mature. The sapling and the last mature tree remain on the board. == '''End Game''' == Logger is a game of equal turns. When a player reaches 10 points, the end game condition is reached. All players who have not had a turn this round will get one final turn. (Example: Player 2 reaches 10 points. Players 3 and 4 will receive one additional turn, but Player 1 does not. However, if Player 4 reaches 10 points, the game ends immediately.) The player with the most points at the end of the game wins. In case of a tie, the player with more protesters in reserve wins. d6595af4f1908aee0c6c669f9f00b2cfe6e939b0 1828 1827 2016-05-19T21:34:41Z Een 3 Link to official rules wikitext text/x-wiki From the official rules: [http://www.icehousegames.org/wiki/index.php?title=Logger|http://www.icehousegames.org/wiki/index.php?title=Logger] == '''Background''' == Four rival lumberjacks are competing to chop down the most trees for their business. However, standing in their way are tree-hugging hippies protesting the deforestation. == '''Glossary''' == The following terms are used in Logger: '''Tree''' - Any seedling, sapling or mature tree on the board. '''Seedling''' - A large pyramid '''Sapling''' - A large pyramid with a medium pyramid stacked on it '''Mature Tree''' - A stack of pyramids. From top to bottom: small, medium, large. '''Protester''' - Denoted by a volcano cap '''Logger''' - A piece representing the player. Denoted by a medium pyramid of a color not used for trees. Non-Icehouse pieces like meeples may be also used. == '''Setup''' == Place a seedling on the center of the board. The remaining pyramid pieces from the Rainbow stash are kept aside in a common pool. Starting with the first player, each player places his logger on a corner of the board. Each player also starts with 1 protester in his or her supply (2 protesters for a 2-player game). Remember who went first as this will be important at the end game. == '''Goal''' == The winner is the player with the most points at the end of the game. Though scoring 10 points triggers the end game, having 10 points may not be enough for victory. == '''Gameplay''' == No Diagonals - Diagonals do not exist in Logger. Any rule pertaining to adjacency or movement is orthogonal only. Each player's turn consists of three parts: Movement, Growth and Action. Movement - Move your logger up to two spaces. Loggers may not occupy or walk through spaces occupied by trees or other loggers. Growth - All trees in the same row and column your logger occupies grow 1 stage. All seedlings become saplings and all saplings become mature trees. Mature trees produce 1 seedling in any space adjacent to them if able. Please note growth of all trees is considered simultaneous, so no tree should experience two stages of growth in one turn, nor should any seedlings newly spawned from a mature tree this turn. All trees in your logger's row and column must grow or create a new seedling if able. Action - There are three options in the Action phase: Plant, Protest and Chop. You must perform an action if able. This phase is skipped if your logger is unable to perform any action. Plant - Plant one seedling in any space adjacent to your logger. Protest - You may place one or more protesters from your supply onto mature trees. Protested trees may not be directly chopped down by any player. Chop - Chop down an unprotested mature tree adjacent to your logger by removing it from the board. Chopping will create a domino effect. Any mature tree behind the first chopped tree will also be considered chopped and so on regardless if they have protesters on them not. This process stops when either the edge of the board or a space occupied by anything other than a mature tree is reached. Score 1 point for each tree removed in this way. Add any protesters from felled trees to your supply. For example, a given row can have this formation: Player-Mature Tree-Mature Tree-Sapling-Mature Tree. When the player chops the first tree, the second one will be removed as well. However, the domino effect ends at the sapling because it is not fully mature. The sapling and the last mature tree remain on the board. == '''End Game''' == Logger is a game of equal turns. When a player reaches 10 points, the end game condition is reached. All players who have not had a turn this round will get one final turn. (Example: Player 2 reaches 10 points. Players 3 and 4 will receive one additional turn, but Player 1 does not. However, if Player 4 reaches 10 points, the game ends immediately.) The player with the most points at the end of the game wins. In case of a tie, the player with more protesters in reserve wins. 0a09aca802f5ba44728c3ffe21d82d707862f9d0 1829 1828 2016-05-19T21:35:03Z Een 3 wikitext text/x-wiki From the official rules: [http://www.icehousegames.org/wiki/index.php?title=Logger http://www.icehousegames.org/wiki/index.php?title=Logger] == '''Background''' == Four rival lumberjacks are competing to chop down the most trees for their business. However, standing in their way are tree-hugging hippies protesting the deforestation. == '''Glossary''' == The following terms are used in Logger: '''Tree''' - Any seedling, sapling or mature tree on the board. '''Seedling''' - A large pyramid '''Sapling''' - A large pyramid with a medium pyramid stacked on it '''Mature Tree''' - A stack of pyramids. From top to bottom: small, medium, large. '''Protester''' - Denoted by a volcano cap '''Logger''' - A piece representing the player. Denoted by a medium pyramid of a color not used for trees. Non-Icehouse pieces like meeples may be also used. == '''Setup''' == Place a seedling on the center of the board. The remaining pyramid pieces from the Rainbow stash are kept aside in a common pool. Starting with the first player, each player places his logger on a corner of the board. Each player also starts with 1 protester in his or her supply (2 protesters for a 2-player game). Remember who went first as this will be important at the end game. == '''Goal''' == The winner is the player with the most points at the end of the game. Though scoring 10 points triggers the end game, having 10 points may not be enough for victory. == '''Gameplay''' == No Diagonals - Diagonals do not exist in Logger. Any rule pertaining to adjacency or movement is orthogonal only. Each player's turn consists of three parts: Movement, Growth and Action. Movement - Move your logger up to two spaces. Loggers may not occupy or walk through spaces occupied by trees or other loggers. Growth - All trees in the same row and column your logger occupies grow 1 stage. All seedlings become saplings and all saplings become mature trees. Mature trees produce 1 seedling in any space adjacent to them if able. Please note growth of all trees is considered simultaneous, so no tree should experience two stages of growth in one turn, nor should any seedlings newly spawned from a mature tree this turn. All trees in your logger's row and column must grow or create a new seedling if able. Action - There are three options in the Action phase: Plant, Protest and Chop. You must perform an action if able. This phase is skipped if your logger is unable to perform any action. Plant - Plant one seedling in any space adjacent to your logger. Protest - You may place one or more protesters from your supply onto mature trees. Protested trees may not be directly chopped down by any player. Chop - Chop down an unprotested mature tree adjacent to your logger by removing it from the board. Chopping will create a domino effect. Any mature tree behind the first chopped tree will also be considered chopped and so on regardless if they have protesters on them not. This process stops when either the edge of the board or a space occupied by anything other than a mature tree is reached. Score 1 point for each tree removed in this way. Add any protesters from felled trees to your supply. For example, a given row can have this formation: Player-Mature Tree-Mature Tree-Sapling-Mature Tree. When the player chops the first tree, the second one will be removed as well. However, the domino effect ends at the sapling because it is not fully mature. The sapling and the last mature tree remain on the board. == '''End Game''' == Logger is a game of equal turns. When a player reaches 10 points, the end game condition is reached. All players who have not had a turn this round will get one final turn. (Example: Player 2 reaches 10 points. Players 3 and 4 will receive one additional turn, but Player 1 does not. However, if Player 4 reaches 10 points, the game ends immediately.) The player with the most points at the end of the game wins. In case of a tie, the player with more protesters in reserve wins. fc8aaf091a7c8f0a438206975e1798ed87088029 Gamehelpsplits 0 181 1830 1338 2016-05-21T07:14:24Z Senatorhung 4176 wikitext text/x-wiki The object of the game is to be the player who occupies the most spaces on the pasture. '''Building the Pasture and Initial Placement''': Each player begins with 4 diamond-shaped pasture tiles. The first player places one of their pasture tiles on the board. The other players place one of their pasture tiles in turn, with each new tile connecting to the existing pasture on at least one side. This continues until each player has placed all 4 of their pasture tiles. Then, again starting with the first player, each player places their entire stack of 16 sheep on any unoccupied pasture along the OUTSIDE border. *Strategy Tip: Games can be won and lost in this phase ! The first player tends to start with an advantage as they have first placement AND first move. You may build the board differently depending on whether you are the first player or one of the subsequent players. In considering initial placement, think about who will act before you and what their likely first move will be. '''Playing the Game''': On your turn, your move consists of splitting a stack of your own sheep into two parts, moving part of the stack in a straight line as far as it can go before hitting another sheep or the border (sheep can not jump over other sheep or gaps). Click on the stack you wish to split. Then, click on the desired destination pasture space. This will split your herd in two halves. Click on the original or destination space to adjust the amount of sheep you want in each herd. You MUST leave at least one sheep on the space on which the original stack was standing. When you are happy with the split, click the 'Validate' option at the top of the game screen. Play continues with each player splitting any one of their stacks. A stack is blocked when it is surrounded by opponents' pieces or the edge, and can no longer be split and moved. *Strategy Tip: Watching out for your biggest herd is usually a sound strategy to start with. Watch out for chokepoints that can be easily closed off leaving you without enough room to spread the rest of your herd. Try not to block yourself in and count your sheep carefully ! '''Ending and Winning the Game''': When all your sheep are blocked, you are eliminated from the game. The game ends when only one player can still split a herd. The winner is the player who succeeds in controlling the most pasture spaces. In the case of a tie, the winner is the player who has the largest number of contiguous pasture spaces occupied by their herd of sheep. cb7bd84d8a62d00dfd54f410172b82ca3ba7e281 Gamehelpcarrara 0 191 1831 1481 2016-05-21T09:02:48Z Senatorhung 4176 wikitext text/x-wiki Link to english rules: https://dl.dropboxusercontent.com/u/720402/Palaces%20of%20Carrara.pdf '''Components''' There are a total of 42 blocks, 7 of each of 6 colours: white, yellow, red, green, blue, and black. There are a total of 30 buildings, in 6 different types, with block costs of 1, 2, 3, 4, and 5. For expansion games, there are an additional 6 buildings, with block costs of 8. They are separated into land (green-coloured) and city (gold-coloured): # villa (land): produces coat of arms objects # castle (land): produces flag objects # cathedral (city): produces cup objects # porta (city): produces gate objects # library (city): produces book objects # palaces (city): produces crown objects 5 of each of these types of objects can be acquired via scoring of cities. 1 of each type can ONLY be purchased for 10 coins from the board after a player's turn action. There are 6 cities on the board where buildings can be built. The buildings can only be built with a sufficient number of blocks that each city will accept. # Livornoa: only white blocks # Pisa: white or yellow blocks # Lucca: white, yellow, or red blocks # Viareggio: white, yellow, red, or green blocks # Massa: white, yellow, red, green, or blue blocks # Lerici: white, yellow, red, green, blue, or black blocks '''Standard vs. Expansion''' The 'standard' game should be considered as a learning setup only since the game becomes one of block buying efficiency. Here are the limitations in the standard game: # turning the block buying wheel is MANDATORY; # there is no separate scoring spot for land or city buildings; # 8.block buildings and their bonus scoring tiles are not available; # you can not upgrade existing buildings; AND # 3 fixed objectives. '''Objectives''' In an expansion game, there are 4 objective categories. There are 6 brown 'top' objectives, 8 purple 'object' objectives, 9 gray 'building' objectives, and 8 green 'bonus vps' objectives. In order for a player to declare the end of the game, they must meet the minimum requirements of the first 3 objectives. The fourth objective is only scored for bonus points at the end of the game. Some objectives are scaled for the number of players. Because of the number of objectives, and how they interact with each other, each game can require very different strategies, leading to excellent game replayability. '''Playing the Game''' Each turn, a player can do 1 of 3 things: # buy blocks; # build a building; OR # score a city or building type. ''''Buying Blocks'''' At the start of each game, there is 1 block of each colour in the first segment of the block wheel, with costs for each colour indicated on the outer rim. A player choosing to buy blocks may choose to turn the wheel one segment to decrease the cost before buying (this turn action is MANDATORY in the standard game). As the wheel is spun, each block becomes progressively cheaper by 1 coin, so that by the final segment, white blocks cost 1 coin, and every other block colour can be purchased for free. After the wheel is spun, a number of blocks are supplied to the first segment until the total number of blocks on the wheel is 11. If the wheel is NOT spun, no new blocks are supplied. Each player starts with 20 coins. After choosing to spin the wheel (or not), the active player can buy as many blocks from a single segment as they wish, as long as they have sufficient coins. Remember, spinning the wheel gives you access to cheaper blocks, but your opponents can also spin on their turns so any blocks you do not buy will get cheaper for them. If there are any blocks remaining in the final (cheapest) segment when the wheel is spun, they remain on the wheel and spin back into the 'first' segment. If, after spinning the wheel, a player does not have enough coins to buy ANY available block, they get 2 coins from the bank which ends their turn. If the wheel is empty and there are no blocks remaining in the supply, players must either build or score instead. ''''Building Buildings'''' Randomly selected, 9 of the 30 basic buildings are placed on the main board. For expansion games, the 6 8.block buildings are also made available beside the board. To build an available building, you first select the one you want, then click above the city where you wish to build it. You then choose which blocks you wish to use to build the building, keeping in mind the block colour restrictions for each city. Blocks used to build in this way are returned to the supply. Another building from the supply (if available), is placed in the empty space on the main board. In expansion games, when you build an 8.block building, you can choose ANY 1 of the 8 bonus scoring tiles, regardless of the city that you built in or the building type. The ones for the cities of Livornoa, Pisa, and Lucca add +1 vp and +1 coin to the base scoring for each of those cities. The ones for the cities of Viareggio, Massa, and Lerici all add +1 vp to the base scoring for each of those cities. The ones for land and city buildings double the vps or coins received when using those scoring spaces. Also only in expansion games, you can upgrade an existing building in a city by paying the difference in block costs between the existing building and the more expensive new building (of any type) that you wish to put in its place. So, to upgrade a 1.block building to a 3.block building, you need to spend 2 blocks, keeping in mind the block colour restriction for the city. ''''Scoring'''' Each player starts with 6 scoring meeples. To score a city, you must have sufficient buildings built in that city. For the cities of Livornoa, Pisa, and Lucca, only 2 buildings are required before those cities can be scored. For the cities of Viareggio, Massa, and Lerici, 3 buildings must be built before they can be scored. You can build more buildings in a city than the minimum before scoring that city, but each city can only be scored ONCE during the game. So, after one player scores a city, they place one of their scoring meeples on that city on the main board, and every other player is blocked from scoring that city. When a city is scored, each building in the city generates an object as long as there are objects of that type in the pool (excludes the 6 objects on the main board, which can only be purchased). As well, each scored city provides a separate bonus, either vps or coins (or both for expansion games after building an 8.block building), with the base score of the city multiplied by the number of blocks used to build the buildings in that city. *So, if you had the 1.block palace, 2.block castle, and 3.block library when you scored viareggio, you would collect 1 crown object, 1 flag object, and 1 book object, along with 1+2+3 (building blocks) * 2 (coins per block basic viareggio bonus) = 12 coins from the bank. Instead of scoring a city, you can choose to score one of the 6 building types, as long as you have built at least 1 of the buildings matching that type. Each building will provide the city score bonus that they are in (including block building multipliers), plus generate an object (if available). Place a scoring meeple on your board to match the type that you are scoring. Opponents can NOT block you from scoring your own buildings in this fashion. For expansion games, you can also score city buildings for coins (with building block multiplier) or land buildings for vps (with building block multiplier). Also for expansion games, after an 8.block building is built, a bonus tile can be placed on the player board. Every subsequent scoring will take into account the extra bonuses for that city or type. If you have used all 6 of your scoring meeples, you can no longer take the scoring action. ''''Buying Objects'''' After each player's action, they have the option to puchase one of the 6 available objects on the main board (1 of each type) for 10 coins. If there are no remaining objects on the board, then no objects may be purchased. '''Ending the Game''' A player can CHOOSE to declare the game end if they successfully meet or exceed the requirements for the first 3 objectives. If they do so, they collect an extra 5 vp for the declaration. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. If no one can or wants to declare the game end, the game ends when all 30 of the buildings on the main board have been built. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. '''Final Scoring''' Any object not included in the #2 purple 'Object' objective is worth 1 vp. Coins are worth 1 vp for every 5 coins (unless you have the 'Top' brown objective that gives a different value). Each player will get vps for any objective cards that they match. Tiebreaker: The player with the most remaining purchased blocks, regardless of colour. 62019634bf538524518ebef59b2a7f3fae51461f 1832 1831 2016-05-21T09:05:17Z Senatorhung 4176 wikitext text/x-wiki Link to english rules: https://dl.dropboxusercontent.com/u/720402/Palaces%20of%20Carrara.pdf '''Components''' There are a total of 42 blocks, 7 of each of 6 colours: white, yellow, red, green, blue, and black. There are a total of 30 buildings, in 6 different types, with block costs of 1, 2, 3, 4, and 5. For expansion games, there are an additional 6 buildings, with block costs of 8. They are separated into land (green-coloured) and city (gold-coloured): # villa (land): produces coat of arms objects # castle (land): produces flag objects # cathedral (city): produces cup objects # porta (city): produces gate objects # library (city): produces book objects # palaces (city): produces crown objects 5 of each of these types of objects can be acquired via scoring of cities. 1 of each type can ONLY be purchased for 10 coins from the board after a player's turn action. There are 6 cities on the board where buildings can be built. The buildings can only be built with a sufficient number of blocks that each city will accept. # Livornoa: only white blocks # Pisa: white or yellow blocks # Lucca: white, yellow, or red blocks # Viareggio: white, yellow, red, or green blocks # Massa: white, yellow, red, green, or blue blocks # Lerici: white, yellow, red, green, blue, or black blocks '''Standard vs. Expansion''' The 'standard' game should be considered as a learning setup only since the game becomes one of block buying efficiency. Here are the limitations in the standard game: # turning the block buying wheel is MANDATORY; # there is no separate scoring spot for land or city buildings; # 8.block buildings and their bonus scoring tiles are not available; # you can not upgrade existing buildings; AND # 3 fixed objectives. '''Objectives''' In an expansion game, there are 4 objective categories. There are 6 brown 'top' objectives, 8 purple 'object' objectives, 9 gray 'building' objectives, and 8 green 'bonus vps' objectives. In order for a player to declare the end of the game, they must meet the minimum requirements of the first 3 objectives. The fourth objective is only scored for bonus points at the end of the game. Some objectives are scaled for the number of players. Because of the number of objectives, and how they interact with each other, each game can require very different strategies, leading to excellent game replayability. '''Playing the Game''' Each turn, a player can do 1 of 3 things: # buy blocks; # build a building; OR # score a city or building type. ''''Buying Blocks'''' At the start of each game, there is 1 block of each colour in the first segment of the block wheel, with costs for each colour indicated on the outer rim. A player choosing to buy blocks may choose to turn the wheel one segment to decrease the cost before buying (this turn action is MANDATORY in the standard game). As the wheel is spun, each block becomes progressively cheaper by 1 coin, so that by the final segment, white blocks cost 1 coin, and every other block colour can be purchased for free. After the wheel is spun, a number of blocks are supplied to the first segment until the total number of blocks on the wheel is 11. If the wheel is NOT spun, no new blocks are supplied. Each player starts with 20 coins. After choosing to spin the wheel (or not), the active player can buy as many blocks from a single segment as they wish, as long as they have sufficient coins. Remember, spinning the wheel gives you access to cheaper blocks, but your opponents can also spin on their turns so any blocks you do not buy will get cheaper for them. If there are any blocks remaining in the final (cheapest) segment when the wheel is spun, they remain on the wheel and spin back into the 'first' segment. If, after spinning the wheel, a player does not have enough coins to buy ANY available block, they get 2 coins from the bank which ends their turn. If the wheel is empty and there are no blocks remaining in the supply, players must either build or score instead. ''''Building Buildings'''' Randomly selected, 9 of the 30 basic buildings are placed on the main board. For expansion games, the 6 8.block buildings are also made available beside the board. To build an available building, you first select the one you want, then click above the city (on your own player board) where you wish to build it. You then choose which blocks you wish to use to build the building, keeping in mind the block colour restrictions for each city. Blocks used to build in this way are returned to the supply. Another building from the supply (if available), is placed in the empty space on the main board. In expansion games, when you build an 8.block building, you can choose ANY 1 of the 8 bonus scoring tiles, regardless of the city that you built in or the building type. The ones for the cities of Livornoa, Pisa, and Lucca add +1 vp and +1 coin to the base scoring for each of those cities. The ones for the cities of Viareggio, Massa, and Lerici all add +1 vp to the base scoring for each of those cities. The ones for land and city buildings double the vps or coins received when using those scoring spaces. Also only in expansion games, you can upgrade an existing building in a city by paying the difference in block costs between the existing building and the more expensive new building (of any type) that you wish to put in its place. So, to upgrade a 1.block building to a 3.block building, you need to spend 2 blocks, keeping in mind the block colour restriction for the city. ''''Scoring'''' Each player starts with 6 scoring meeples. To score a city, you must have sufficient buildings built in that city. For the cities of Livornoa, Pisa, and Lucca, only 2 buildings are required before those cities can be scored. For the cities of Viareggio, Massa, and Lerici, 3 buildings must be built before they can be scored. You can build more buildings in a city than the minimum before scoring that city, but each city can only be scored ONCE during the game. So, after one player scores a city, they place one of their scoring meeples on that city on the main board, and every other player is blocked from scoring that city. When a city is scored, each building in the city generates an object as long as there are objects of that type in the pool (excludes the 6 objects on the main board, which can only be purchased). As well, each scored city provides a separate bonus, either vps or coins (or both for expansion games after building an 8.block building), with the base score of the city multiplied by the number of blocks used to build the buildings in that city. *So, if you had the 1.block palace, 2.block castle, and 3.block library when you scored viareggio, you would collect 1 crown object, 1 flag object, and 1 book object, along with 1+2+3 (building blocks) * 2 (coins per block basic viareggio bonus) = 12 coins from the bank. Instead of scoring a city, you can choose to score one of the 6 building types, as long as you have built at least 1 of the buildings matching that type. Each building will provide the city score bonus that they are in (including block building multipliers), plus generate an object (if available). Place a scoring meeple on your board to match the type that you are scoring. Opponents can NOT block you from scoring your own buildings in this fashion. For expansion games, you can also score city buildings for coins (with building block multiplier) or land buildings for vps (with building block multiplier). Also for expansion games, after an 8.block building is built, a bonus tile can be placed on the player board. Every subsequent scoring will take into account the extra bonuses for that city or type. If you have used all 6 of your scoring meeples, you can no longer take the scoring action. ''''Buying Objects'''' After each player's action, they have the option to puchase one of the 6 available objects on the main board (1 of each type) for 10 coins. If there are no remaining objects on the board, then no objects may be purchased. '''Ending the Game''' A player can CHOOSE to declare the game end if they successfully meet or exceed the requirements for the first 3 objectives. If they do so, they collect an extra 5 vp for the declaration. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. If no one can or wants to declare the game end, the game ends when all 30 of the buildings on the main board have been built. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. '''Final Scoring''' Any object not included in the #2 purple 'Object' objective is worth 1 vp. Coins are worth 1 vp for every 5 coins (unless you have the 'Top' brown objective that gives a different value). Each player will get vps for any objective cards that they match. Tiebreaker: The player with the most remaining purchased blocks, regardless of colour. ca8abb2dfc1ced998069d8689395a9563a7ce7d5 1833 1832 2016-05-21T09:06:43Z Senatorhung 4176 wikitext text/x-wiki Link to english rules: https://dl.dropboxusercontent.com/u/720402/Palaces%20of%20Carrara.pdf '''Components''' There are a total of 42 blocks, 7 of each of 6 colours: white, yellow, red, green, blue, and black. There are a total of 30 buildings, in 6 different types, with block costs of 1, 2, 3, 4, and 5. For expansion games, there are an additional 6 buildings, with block costs of 8. They are separated into land (green-coloured) and city (gold-coloured): # villa (land): produces coat of arms objects # castle (land): produces flag objects # cathedral (city): produces cup objects # porta (city): produces gate objects # library (city): produces book objects # palaces (city): produces crown objects 5 of each of these types of objects can be acquired via scoring of cities. 1 of each type can ONLY be purchased for 10 coins from the board after a player's turn action. There are 6 cities on the board where buildings can be built. The buildings can only be built with a sufficient number of blocks that each city will accept. # Livornoa: only white blocks # Pisa: white or yellow blocks # Lucca: white, yellow, or red blocks # Viareggio: white, yellow, red, or green blocks # Massa: white, yellow, red, green, or blue blocks # Lerici: white, yellow, red, green, blue, or black blocks '''Standard vs. Expansion''' The 'standard' game should be considered as a learning setup only since the game becomes one of block buying efficiency. Here are the limitations in the standard game: # turning the block buying wheel is MANDATORY; # there is no separate scoring spot for land or city buildings; # 8.block buildings and their bonus scoring tiles are not available; # you can not upgrade existing buildings; AND # 3 fixed objectives. '''Objectives''' In an expansion game, there are 4 objective categories. There are 6 brown 'top' objectives, 8 purple 'object' objectives, 9 gray 'building' objectives, and 8 green 'bonus vps' objectives. In order for a player to declare the end of the game, they must meet the minimum requirements of the first 3 objectives. The fourth objective is only scored for bonus points at the end of the game. Some objectives are scaled for the number of players. Because of the number of objectives, and how they interact with each other, each game can require very different strategies, leading to excellent game replayability. '''Playing the Game''' Each turn, a player can do 1 of 3 things: # buy blocks; # build a building; OR # score a city or building type. ''''Buying Blocks'''' At the start of each game, there is 1 block of each colour in the first segment of the block wheel, with costs for each colour indicated on the outer rim. A player choosing to buy blocks may choose to turn the wheel one segment to decrease the cost before buying (this turn action is MANDATORY in the standard game). As the wheel is spun, each block becomes progressively cheaper by 1 coin, so that by the final segment, white blocks cost 1 coin, and every other block colour can be purchased for free. After the wheel is spun, a number of blocks are supplied to the first segment until the total number of blocks on the wheel is 11. If the wheel is NOT spun, no new blocks are supplied. Each player starts with 20 coins. After choosing to spin the wheel (or not), the active player can buy as many blocks from a single segment as they wish, as long as they have sufficient coins. Remember, spinning the wheel gives you access to cheaper blocks, but your opponents can also spin on their turns so any blocks you do not buy will get cheaper for them. If there are any blocks remaining in the final (cheapest) segment when the wheel is spun, they remain on the wheel and spin back into the 'first' segment. If, after spinning the wheel, a player does not have enough coins to buy ANY available block, they get 2 coins from the bank which ends their turn. If the wheel is empty and there are no blocks remaining in the supply, players must either build or score instead. ''''Building Buildings'''' Randomly selected, 9 of the 30 basic buildings are placed on the main board. For expansion games, the 6 8.block buildings are also made available beside the board. To build an available building, you first select the one you want, then click above the city (on your own player board) where you wish to build it. You then choose which blocks you wish to use to build the building, keeping in mind the block colour restrictions for each city. Blocks used to build in this way are returned to the supply. Another building from the supply (if available), is placed in the empty space on the main board. In expansion games, when you build an 8.block building, you can choose ANY 1 of the 8 bonus scoring tiles, regardless of the city that you built in or the building type. The ones for the cities of Livornoa, Pisa, and Lucca add +1 vp and +1 coin to the base scoring for each of those cities. The ones for the cities of Viareggio, Massa, and Lerici all add +1 vp to the base scoring for each of those cities. The ones for land and city buildings double the vps or coins received when using those scoring spaces. Also only in expansion games, you can upgrade an existing building in a city by paying the difference in block costs between the existing building and the more expensive new building (of any type) that you wish to put in its place. So, to upgrade a 1.block building to a 3.block building, you need to spend 2 blocks, keeping in mind the block colour restriction for the city. ''''Scoring'''' Each player starts with 6 scoring meeples. If you have used all 6 of your scoring meeples, you can no longer take the scoring action. To score a city, you must have sufficient buildings built in that city. For the cities of Livornoa, Pisa, and Lucca, only 2 buildings are required before those cities can be scored. For the cities of Viareggio, Massa, and Lerici, 3 buildings must be built before they can be scored. You can build more buildings in a city than the minimum before scoring that city, but each city can only be scored ONCE during the game. So, after one player scores a city, they place one of their scoring meeples on that city on the main board, and every other player is blocked from scoring that city. When a city is scored, each building in the city generates an object as long as there are objects of that type in the pool (excludes the 6 objects on the main board, which can only be purchased). As well, each scored city provides a separate bonus, either vps or coins (or both for expansion games after building an 8.block building), with the base score of the city multiplied by the number of blocks used to build the buildings in that city. *So, if you had the 1.block palace, 2.block castle, and 3.block library when you scored viareggio, you would collect 1 crown object, 1 flag object, and 1 book object, along with 1+2+3 (building blocks) * 2 (coins per block basic viareggio bonus) = 12 coins from the bank. Instead of scoring a city, you can choose to score one of the 6 building types, as long as you have built at least 1 of the buildings matching that type. Each building will provide the city score bonus that they are in (including block building multipliers), plus generate an object (if available). Place a scoring meeple on your board to match the type that you are scoring. Opponents can NOT block you from scoring your own buildings in this fashion. For expansion games, you can also score city buildings for coins (with building block multiplier) or land buildings for vps (with building block multiplier). Also for expansion games, after an 8.block building is built, a bonus tile can be placed on the player board. Every subsequent scoring will take into account the extra bonuses for that city or type. ''''Buying Objects'''' After each player's action, they have the option to puchase one of the 6 available objects on the main board (1 of each type) for 10 coins. If there are no remaining objects on the board, then no objects may be purchased. '''Ending the Game''' A player can CHOOSE to declare the game end if they successfully meet or exceed the requirements for the first 3 objectives. If they do so, they collect an extra 5 vp for the declaration. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. If no one can or wants to declare the game end, the game ends when all 30 of the buildings on the main board have been built. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. '''Final Scoring''' Any object not included in the #2 purple 'Object' objective is worth 1 vp. Coins are worth 1 vp for every 5 coins (unless you have the 'Top' brown objective that gives a different value). Each player will get vps for any objective cards that they match. Tiebreaker: The player with the most remaining purchased blocks, regardless of colour. b84f8c126624400854f5c76936b6d825cb5a8e28 1834 1833 2016-05-21T09:08:41Z Senatorhung 4176 wikitext text/x-wiki Link to english rules: https://dl.dropboxusercontent.com/u/720402/Palaces%20of%20Carrara.pdf '''Components''' There are a total of 42 blocks, 7 of each of 6 colours: white, yellow, red, green, blue, and black. There are a total of 30 buildings, in 6 different types, with block costs of 1, 2, 3, 4, and 5. For expansion games, there are an additional 6 buildings, with block costs of 8. They are separated into land (green-coloured) and city (gold-coloured): # villa (land): produces coat of arms objects # castle (land): produces flag objects # cathedral (city): produces cup objects # porta (city): produces gate objects # library (city): produces book objects # palaces (city): produces crown objects 5 of each of these types of objects can be acquired via scoring of cities. 1 of each type can ONLY be purchased for 10 coins from the board after a player's turn action. There are 6 cities on the board where buildings can be built. The buildings can only be built with a sufficient number of blocks that each city will accept. # Livornoa: only white blocks # Pisa: white or yellow blocks # Lucca: white, yellow, or red blocks # Viareggio: white, yellow, red, or green blocks # Massa: white, yellow, red, green, or blue blocks # Lerici: white, yellow, red, green, blue, or black blocks '''Standard vs. Expansion''' The 'standard' game should be considered as a learning setup only since the game becomes one of block buying efficiency. Here are the limitations in the standard game: # turning the block buying wheel is MANDATORY; # there is no separate scoring spot for land or city buildings; # 8.block buildings and their bonus scoring tiles are not available; # you can not upgrade existing buildings; AND # 3 fixed objectives. '''Objectives''' In an expansion game, there are 4 objective categories. There are 6 brown 'top' objectives, 8 purple 'object' objectives, 9 gray 'building' objectives, and 8 green 'bonus vps' objectives. In order for a player to declare the end of the game, they must meet the minimum requirements of the first 3 objectives. The fourth objective is only scored for bonus points at the end of the game. Some objectives are scaled for the number of players. Because of the number of objectives, and how they interact with each other, each game can require very different strategies, leading to excellent game replayability. '''Playing the Game''' Each turn, a player can do 1 of 3 things: # buy blocks; # build a building; OR # score a city or building type. ''''Buying Blocks'''' At the start of each game, there is 1 block of each colour in the first segment of the block wheel, with costs for each colour indicated on the outer rim. A player choosing to buy blocks may choose to turn the wheel one segment to decrease the cost before buying (this turn action is MANDATORY in the standard game). As the wheel is spun, each block becomes progressively cheaper by 1 coin, so that by the final segment, white blocks cost 1 coin, and every other block colour can be purchased for free. After the wheel is spun, a number of blocks are supplied to the first segment until the total number of blocks on the wheel is 11. If the wheel is NOT spun, no new blocks are supplied. Each player starts with 20 coins. After choosing to spin the wheel (or not), the active player can buy as many blocks from a single segment as they wish, as long as they have sufficient coins. Remember, spinning the wheel gives you access to cheaper blocks, but your opponents can also spin on their turns so any blocks you do not buy will get cheaper for them. If there are any blocks remaining in the final (cheapest) segment when the wheel is spun, they remain on the wheel and spin back into the 'first' segment. If, after spinning the wheel, a player does not have enough coins to buy ANY available block, they get 2 coins from the bank which ends their turn. If the wheel is empty and there are no blocks remaining in the supply, players must either build or score instead. ''''Building Buildings'''' Randomly selected, 9 of the 30 basic buildings are placed on the main board. For expansion games, the 6 8.block buildings are also made available beside the board. To build an available building, you first select the one you want, then click above the city (on your own player board) where you wish to build it. You then choose which blocks you wish to use to build the building, keeping in mind the block colour restrictions for each city. Blocks used to build in this way are returned to the supply. Another building from the supply (if available), is placed in the empty space on the main board. In expansion games, when you build an 8.block building, you can choose ANY 1 of the 8 bonus scoring tiles, regardless of the city that you built in or the building type. The ones for the cities of Livornoa, Pisa, and Lucca add +1 vp and +1 coin to the base scoring for each of those cities. The ones for the cities of Viareggio, Massa, and Lerici all add +1 vp to the base scoring for each of those cities. The ones for land and city buildings double the vps or coins received when using those scoring spaces. Also only in expansion games, you can upgrade an existing building in a city by paying the difference in block costs between the existing building and the more expensive new building (of any type) that you wish to put in its place. So, to upgrade a 1.block building to a 3.block building, you need to spend 2 blocks, keeping in mind the block colour restriction for the city. ''''Scoring'''' Each player starts with 6 scoring meeples. If you have used all 6 of your scoring meeples, you can no longer take the scoring action. To score a city, you must have sufficient buildings built in that city. For the cities of Livornoa, Pisa, and Lucca, only 2 buildings are required before those cities can be scored. For the cities of Viareggio, Massa, and Lerici, 3 buildings must be built before they can be scored. You can build more buildings in a city than the minimum before scoring that city, but each city can only be scored ONCE during the game. So, after one player scores a city, they place one of their scoring meeples on that city on the main board, and every other player is blocked from scoring that city. When a city is scored, each building in the city generates an object as long as there are objects of that type in the pool (excludes the 6 objects on the main board, which can only be purchased). As well, each scored city provides a separate bonus, either vps or coins (or both for expansion games after building an 8.block building), with the base score of the city multiplied by the number of blocks used to build the buildings in that city. *So, if you had the 1.block palace, 2.block castle, and 3.block library when you scored viareggio, you would collect 1 crown object, 1 flag object, and 1 book object, along with 1+2+3 (building blocks) * 2 (coins per block basic viareggio bonus) = 12 coins from the bank. Instead of scoring a city, you can choose to score one of the 6 building types, as long as you have built at least 1 of the buildings matching that type. Each building will provide the city score bonus that they are in (including block building multipliers), plus generate an object (if available). Place a scoring meeple on your board to match the type that you are scoring. Opponents can NOT block you from scoring your own buildings in this fashion, but once you have scored a building or type, you can not score that spot again. For expansion games, you can also score city buildings for coins (with building block multiplier) or land buildings for vps (with building block multiplier). Also for expansion games, after an 8.block building is built, a bonus tile can be placed on the player board. Every subsequent scoring will take into account the extra bonuses for that city or type. ''''Buying Objects'''' After each player's action, they have the option to puchase one of the 6 available objects on the main board (1 of each type) for 10 coins. If there are no remaining objects on the board, then no objects may be purchased. '''Ending the Game''' A player can CHOOSE to declare the game end if they successfully meet or exceed the requirements for the first 3 objectives. If they do so, they collect an extra 5 vp for the declaration. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. If no one can or wants to declare the game end, the game ends when all 30 of the buildings on the main board have been built. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. '''Final Scoring''' Any object not included in the #2 purple 'Object' objective is worth 1 vp. Coins are worth 1 vp for every 5 coins (unless you have the 'Top' brown objective that gives a different value). Each player will get vps for any objective cards that they match. Tiebreaker: The player with the most remaining purchased blocks, regardless of colour. aef349503dd870dde9d010b5b37f0378912a34d4 1835 1834 2016-05-21T09:09:42Z Senatorhung 4176 wikitext text/x-wiki Link to english rules: https://dl.dropboxusercontent.com/u/720402/Palaces%20of%20Carrara.pdf '''Components''' There are a total of 42 blocks, 7 of each of 6 colours: white, yellow, red, green, blue, and black. There are a total of 30 buildings, in 6 different types, with block costs of 1, 2, 3, 4, and 5. For expansion games, there are an additional 6 buildings, with block costs of 8. They are separated into land (green-coloured) and city (gold-coloured): # villa (land): produces coat of arms objects # castle (land): produces flag objects # cathedral (city): produces cup objects # porta (city): produces gate objects # library (city): produces book objects # palaces (city): produces crown objects 5 of each of these types of objects can be acquired via scoring of cities. 1 of each type can ONLY be purchased for 10 coins from the board after a player's turn action. There are 6 cities on the board where buildings can be built. The buildings can only be built with a sufficient number of blocks that each city will accept. # Livornoa: only white blocks # Pisa: white or yellow blocks # Lucca: white, yellow, or red blocks # Viareggio: white, yellow, red, or green blocks # Massa: white, yellow, red, green, or blue blocks # Lerici: white, yellow, red, green, blue, or black blocks '''Standard vs. Expansion''' The 'standard' game should be considered as a learning setup only since the game becomes one of block buying efficiency. Here are the limitations in the standard game: # turning the block buying wheel is MANDATORY; # there is no separate scoring spot for land or city buildings; # 8.block buildings and their bonus scoring tiles are not available; # you can not upgrade existing buildings; AND # 3 fixed objectives. '''Objectives''' In an expansion game, there are 4 objective categories. There are 6 brown 'top' objectives, 8 purple 'object' objectives, 9 gray 'building' objectives, and 8 green 'bonus vps' objectives. In order for a player to declare the end of the game, they must meet the minimum requirements of the first 3 objectives. The fourth objective is only scored for bonus points at the end of the game. Some objectives are scaled for the number of players. Because of the number of objectives, and how they interact with each other, each game can require very different strategies, leading to excellent game replayability. '''Playing the Game''' Each turn, a player can do 1 of 3 things: # buy blocks; # build a building; OR # score a city or building type. ''''Buying Blocks'''' At the start of each game, there is 1 block of each colour in the first segment of the block wheel, with costs for each colour indicated on the outer rim. A player choosing to buy blocks may choose to turn the wheel one segment to decrease the cost before buying (this turn action is MANDATORY in the standard game). As the wheel is spun, each block becomes progressively cheaper by 1 coin, so that by the final segment, white blocks cost 1 coin, and every other block colour can be purchased for free. After the wheel is spun, a number of blocks are supplied to the first segment until the total number of blocks on the wheel is 11. If the wheel is NOT spun, no new blocks are supplied. Each player starts with 20 coins. After choosing to spin the wheel (or not), the active player can buy as many blocks from a single segment as they wish, as long as they have sufficient coins. Remember, spinning the wheel gives you access to cheaper blocks, but your opponents can also spin on their turns so any blocks you do not buy will get cheaper for them. If there are any blocks remaining in the final (cheapest) segment when the wheel is spun, they remain on the wheel and spin back into the 'first' segment. If, after spinning the wheel, a player does not have enough coins to buy ANY available block, they get 2 coins from the bank which ends their turn. If the wheel is empty and there are no blocks remaining in the supply, players must either build or score instead. ''''Building Buildings'''' Randomly selected, 9 of the 30 basic buildings are placed on the main board. For expansion games, the 6 8.block buildings are also made available beside the board. To build an available building, you first select the one you want, then click above the city (on your own player board) where you wish to build it. You then choose which blocks you wish to use to build the building, keeping in mind the block colour restrictions for each city. Blocks used to build in this way are returned to the supply. Another building from the supply (if available), is placed in the empty space on the main board. In expansion games, when you build an 8.block building, you can choose ANY 1 of the 8 bonus scoring tiles, regardless of the city that you built in or the building type. The ones for the cities of Livornoa, Pisa, and Lucca add +1 vp and +1 coin to the base scoring for each of those cities. The ones for the cities of Viareggio, Massa, and Lerici all add +1 vp to the base scoring for each of those cities. The ones for land and city buildings double the vps or coins received when using those scoring spaces. Also only in expansion games, you can upgrade an existing building in a city by paying the difference in block costs between the existing building and the more expensive new building (of any type) that you wish to put in its place. So, to upgrade a 1.block building to a 3.block building, you need to spend 2 blocks, keeping in mind the block colour restriction for the city. ''''Scoring'''' Each player starts with 6 scoring meeples. If you have used all 6 of your scoring meeples, you can no longer take the scoring action. To score a city, you must have sufficient buildings built in that city. For the cities of Livornoa, Pisa, and Lucca, only 2 buildings are required before those cities can be scored. For the cities of Viareggio, Massa, and Lerici, 3 buildings must be built before they can be scored. You can build more buildings in a city than the minimum before scoring that city, but each city can only be scored ONCE during the game. So, after one player scores a city, they place one of their scoring meeples on that city on the main board, and every other player is blocked from scoring that city. When a city is scored, each building in the city generates an object as long as there are objects of that type in the pool (excludes the 6 objects on the main board, which can only be purchased). As well, each scored city provides a separate bonus, either vps or coins (or both for expansion games after building an 8.block building), with the base score of the city multiplied by the number of blocks used to build the buildings in that city. *So, if you had the 1.block palace, 2.block castle, and 3.block library when you scored viareggio, you would collect 1 crown object, 1 flag object, and 1 book object, along with 1+2+3 (building blocks) * 2 (coins per block basic viareggio bonus) = 12 coins from the bank. Instead of scoring a city, you can choose to score one of the 6 building types, as long as you have built at least 1 of the buildings matching that type. Each building will provide the city score bonus that they are in (including block building multipliers), plus generate an object (if available). Place a scoring meeple on your board to match the type that you are scoring. Opponents can NOT block you from scoring your own building types in this fashion, but once you have scored a type, you can not score that again. For expansion games, you can also score city buildings for coins (with building block multiplier) or land buildings for vps (with building block multiplier). Also for expansion games, after an 8.block building is built, a bonus tile can be placed on the player board. Every subsequent scoring will take into account the extra bonuses for that city or type. ''''Buying Objects'''' After each player's action, they have the option to puchase one of the 6 available objects on the main board (1 of each type) for 10 coins. If there are no remaining objects on the board, then no objects may be purchased. '''Ending the Game''' A player can CHOOSE to declare the game end if they successfully meet or exceed the requirements for the first 3 objectives. If they do so, they collect an extra 5 vp for the declaration. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. If no one can or wants to declare the game end, the game ends when all 30 of the buildings on the main board have been built. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. '''Final Scoring''' Any object not included in the #2 purple 'Object' objective is worth 1 vp. Coins are worth 1 vp for every 5 coins (unless you have the 'Top' brown objective that gives a different value). Each player will get vps for any objective cards that they match. Tiebreaker: The player with the most remaining purchased blocks, regardless of colour. a9f469d5beb6e43ff7bc84786afcd13787d13645 1836 1835 2016-05-21T09:10:29Z Senatorhung 4176 wikitext text/x-wiki Link to english rules: https://dl.dropboxusercontent.com/u/720402/Palaces%20of%20Carrara.pdf '''Components''' There are a total of 42 blocks, 7 of each of 6 colours: white, yellow, red, green, blue, and black. There are a total of 30 buildings, in 6 different types, with block costs of 1, 2, 3, 4, and 5. For expansion games, there are an additional 6 buildings, with block costs of 8. They are separated into land (green-coloured) and city (gold-coloured): # villa (land): produces coat of arms objects # castle (land): produces flag objects # cathedral (city): produces cup objects # porta (city): produces gate objects # library (city): produces book objects # palaces (city): produces crown objects 5 of each of these types of objects can be acquired via scoring of cities. 1 of each type can ONLY be purchased for 10 coins from the board after a player's turn action. There are 6 cities on the board where buildings can be built. The buildings can only be built with a sufficient number of blocks that each city will accept. # Livornoa: only white blocks # Pisa: white or yellow blocks # Lucca: white, yellow, or red blocks # Viareggio: white, yellow, red, or green blocks # Massa: white, yellow, red, green, or blue blocks # Lerici: white, yellow, red, green, blue, or black blocks '''Standard vs. Expansion''' The 'standard' game should be considered as a learning setup only since the game becomes one of block buying efficiency. Here are the limitations in the standard game: # turning the block buying wheel is MANDATORY; # there is no separate scoring spot for land or city buildings; # 8.block buildings and their bonus scoring tiles are not available; # you can not upgrade existing buildings; AND # 3 fixed objectives. '''Objectives''' In an expansion game, there are 4 objective categories. There are 6 brown 'top' objectives, 8 purple 'object' objectives, 9 gray 'building' objectives, and 8 green 'bonus vps' objectives. In order for a player to declare the end of the game, they must meet the minimum requirements of the first 3 objectives. The fourth objective is only scored for bonus points at the end of the game. Some objectives are scaled for the number of players. Because of the number of objectives, and how they interact with each other, each game can require very different strategies, leading to excellent game replayability. '''Playing the Game''' Each turn, a player can do 1 of 3 things: # buy blocks; # build a building; OR # score a city or building type. ''''Buying Blocks'''' At the start of each game, there is 1 block of each colour in the first segment of the block wheel, with costs for each colour indicated on the outer rim. A player choosing to buy blocks may choose to turn the wheel one segment to decrease the cost before buying (this turn action is MANDATORY in the standard game). As the wheel is spun, each block becomes progressively cheaper by 1 coin, so that by the final segment, white blocks cost 1 coin, and every other block colour can be purchased for free. After the wheel is spun, a number of blocks are supplied to the first segment until the total number of blocks on the wheel is 11. If the wheel is NOT spun, no new blocks are supplied. Each player starts with 20 coins. After choosing to spin the wheel (or not), the active player can buy as many blocks from a single segment as they wish, as long as they have sufficient coins. Remember, spinning the wheel gives you access to cheaper blocks, but your opponents can also spin on their turns so any blocks you do not buy will get cheaper for them. If there are any blocks remaining in the final (cheapest) segment when the wheel is spun, they remain on the wheel and spin back into the 'first' segment. If, after spinning the wheel, a player does not have enough coins to buy ANY available block, they get 2 coins from the bank which ends their turn. If the wheel is empty and there are no blocks remaining in the supply, players must either build or score instead. ''''Building Buildings'''' Randomly selected, 9 of the 30 basic buildings are placed on the main board. For expansion games, the 6 8.block buildings are also made available beside the board. To build an available building, you first select the one you want, then click above the city (on your own player board) where you wish to build it. You then choose which blocks you wish to use to build the building, keeping in mind the block colour restrictions for each city. Blocks used to build in this way are returned to the supply. Another building from the supply (if available), is placed in the empty space on the main board. In expansion games, when you build an 8.block building, you can choose ANY 1 of the 8 bonus scoring tiles, regardless of the city that you built in or the building type. The ones for the cities of Livornoa, Pisa, and Lucca add +1 vp and +1 coin to the base scoring for each of those cities. The ones for the cities of Viareggio, Massa, and Lerici all add +1 vp to the base scoring for each of those cities. The ones for land and city buildings double the vps or coins received when using those scoring spaces. Also only in expansion games, you can upgrade an existing building in a city by paying the difference in block costs between the existing building and the more expensive new building (of any type) that you wish to put in its place. So, to upgrade a 1.block building to a 3.block building, you need to spend 2 blocks, keeping in mind the block colour restriction for the city. ''''Scoring'''' Each player starts with 6 scoring meeples. If you have used all 6 of your scoring meeples, you can no longer take the scoring action. To score a city, you must have sufficient buildings built in that city. For the cities of Livornoa, Pisa, and Lucca, only 2 buildings are required before those cities can be scored. For the cities of Viareggio, Massa, and Lerici, 3 buildings must be built before they can be scored. You can build more buildings in a city than the minimum before scoring that city, but each city can only be scored ONCE during the game. So, after one player scores a city, they place one of their scoring meeples on that city on the main board, and every other player is blocked from scoring that city. When a city is scored, each building in the city generates an object as long as there are objects of that type in the pool (excludes the 6 objects on the main board, which can only be purchased). As well, each scored city provides a separate bonus, either vps or coins (or both for expansion games after building an 8.block building), with the base score of the city multiplied by the number of blocks used to build the buildings in that city. *So, if you had the 1.block palace, 2.block castle, and 3.block library when you scored viareggio, you would collect 1 crown object, 1 flag object, and 1 book object, along with 1+2+3 (building blocks) * 2 (coins per block basic viareggio bonus) = 12 coins from the bank. Instead of scoring a city, you can choose to score one of the 6 building types, as long as you have built at least 1 of the buildings matching that type. Each building will provide the city score bonus that they are in (including block building multipliers), plus generate an object (if available). Place a scoring meeple on your board to match the type that you are scoring. Opponents can NOT block you from scoring your own building types in this fashion, but once you have scored a type, you can not score that again. For expansion games, you can also score city buildings for coins (with building block multiplier) or land buildings for vps (with building block multiplier). Also for expansion games, after an 8.block building is built, a bonus tile can be placed on the player board. Every subsequent scoring will take into account the extra bonuses for that city or type. ''''Buying Objects'''' After each player's action, they have the option to puchase one of the 6 available objects on the main board (1 of each type) for 10 coins. If there are no remaining objects on the board, then no objects may be purchased. '''Ending the Game''' A player can CHOOSE to declare the game end if they successfully meet or exceed the requirements for the first 3 objectives. If they do so, they collect 5 vp for the declaration. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. If no one can or wants to declare the game end, the game ends when all 30 of the buildings on the main board have been built. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. '''Final Scoring''' Any object not included in the #2 purple 'Object' objective is worth 1 vp. Coins are worth 1 vp for every 5 coins (unless you have the 'Top' brown objective that gives a different value). Each player will get vps for any objective cards that they match. Tiebreaker: The player with the most remaining purchased blocks, regardless of colour. e04df28cd61e667cf4f5609925a780eff5c22286 1837 1836 2016-05-21T09:11:08Z Senatorhung 4176 wikitext text/x-wiki Link to english rules: https://dl.dropboxusercontent.com/u/720402/Palaces%20of%20Carrara.pdf '''Components''' There are a total of 42 blocks, 7 of each of 6 colours: white, yellow, red, green, blue, and black. There are a total of 30 buildings, in 6 different types, with block costs of 1, 2, 3, 4, and 5. For expansion games, there are an additional 6 buildings, with block costs of 8. They are separated into land (green-coloured) and city (gold-coloured): # villa (land): produces coat of arms objects # castle (land): produces flag objects # cathedral (city): produces cup objects # porta (city): produces gate objects # library (city): produces book objects # palaces (city): produces crown objects 5 of each of these types of objects can be acquired via scoring of cities. 1 of each type can ONLY be purchased for 10 coins from the board after a player's turn action. There are 6 cities on the board where buildings can be built. The buildings can only be built with a sufficient number of blocks that each city will accept. # Livornoa: only white blocks # Pisa: white or yellow blocks # Lucca: white, yellow, or red blocks # Viareggio: white, yellow, red, or green blocks # Massa: white, yellow, red, green, or blue blocks # Lerici: white, yellow, red, green, blue, or black blocks '''Standard vs. Expansion''' The 'standard' game should be considered as a learning setup only since the game becomes one of block buying efficiency. Here are the limitations in the standard game: # turning the block buying wheel is MANDATORY; # there is no separate scoring spot for land or city buildings; # 8.block buildings and their bonus scoring tiles are not available; # you can not upgrade existing buildings; AND # 3 fixed objectives. '''Objectives''' In an expansion game, there are 4 objective categories. There are 6 brown 'top' objectives, 8 purple 'object' objectives, 9 gray 'building' objectives, and 8 green 'bonus vps' objectives. In order for a player to declare the end of the game, they must meet the minimum requirements of the first 3 objectives. The fourth objective is only scored for bonus points at the end of the game. Some objectives are scaled for the number of players. Because of the number of objectives, and how they interact with each other, each game can require very different strategies, leading to excellent game replayability. '''Playing the Game''' Each turn, a player can do 1 of 3 things: # buy blocks; # build a building; OR # score a city or building type. ''''Buying Blocks'''' At the start of each game, there is 1 block of each colour in the first segment of the block wheel, with costs for each colour indicated on the outer rim. A player choosing to buy blocks may choose to turn the wheel one segment to decrease the cost before buying (this turn action is MANDATORY in the standard game). As the wheel is spun, each block becomes progressively cheaper by 1 coin, so that by the final segment, white blocks cost 1 coin, and every other block colour can be purchased for free. After the wheel is spun, a number of blocks are supplied to the first segment until the total number of blocks on the wheel is 11. If the wheel is NOT spun, no new blocks are supplied. Each player starts with 20 coins. After choosing to spin the wheel (or not), the active player can buy as many blocks from a single segment as they wish, as long as they have sufficient coins. Remember, spinning the wheel gives you access to cheaper blocks, but your opponents can also spin on their turns so any blocks you do not buy will get cheaper for them. If there are any blocks remaining in the final (cheapest) segment when the wheel is spun, they remain on the wheel and spin back into the 'first' segment. If, after spinning the wheel, a player does not have enough coins to buy ANY available block, they get 2 coins from the bank which ends their turn. If the wheel is empty and there are no blocks remaining in the supply, players must either build or score instead. ''''Building Buildings'''' Randomly selected, 9 of the 30 basic buildings are placed on the main board. For expansion games, the 6 8.block buildings are also made available beside the board. To build an available building, you first select the one you want, then click above the city (on your own player board) where you wish to build it. You then choose which blocks you wish to use to build the building, keeping in mind the block colour restrictions for each city. Blocks used to build in this way are returned to the supply. Another building from the supply (if available), is placed in the empty space on the main board. In expansion games, when you build an 8.block building, you can choose ANY 1 of the 8 bonus scoring tiles, regardless of the city that you built in or the building type. The ones for the cities of Livornoa, Pisa, and Lucca add +1 vp and +1 coin to the base scoring for each of those cities. The ones for the cities of Viareggio, Massa, and Lerici all add +1 vp to the base scoring for each of those cities. The ones for land and city buildings double the vps or coins received when using those scoring spaces. Also only in expansion games, you can upgrade an existing building in a city by paying the difference in block costs between the existing building and the more expensive new building (of any type) that you wish to put in its place. So, to upgrade a 1.block building to a 3.block building, you need to spend 2 blocks, keeping in mind the block colour restriction for the city. ''''Scoring'''' Each player starts with 6 scoring meeples. If you have used all 6 of your scoring meeples, you can no longer take the scoring action. To score a city, you must have sufficient buildings built in that city. For the cities of Livornoa, Pisa, and Lucca, only 2 buildings are required before those cities can be scored. For the cities of Viareggio, Massa, and Lerici, 3 buildings must be built before they can be scored. You can build more buildings in a city than the minimum before scoring that city, but each city can only be scored ONCE during the game. So, after one player scores a city, they place one of their scoring meeples on that city on the main board, and every other player is blocked from scoring that city. When a city is scored, each building in the city generates an object as long as there are objects of that type in the pool (excludes the 6 objects on the main board, which can only be purchased). As well, each scored city provides a separate bonus, either vps or coins (or both for expansion games after building an 8.block building), with the base score of the city multiplied by the number of blocks used to build the buildings in that city. *So, if you had the 1.block palace, 2.block castle, and 3.block library when you scored viareggio, you would collect 1 crown object, 1 flag object, and 1 book object, along with 1+2+3 (building blocks) * 2 (coins per block basic viareggio bonus) = 12 coins from the bank. Instead of scoring a city, you can choose to score one of the 6 building types, as long as you have built at least 1 of the buildings matching that type. Each building will provide the city score bonus that they are in (including block building multipliers), plus generate an object (if available). Place a scoring meeple on your board to match the type that you are scoring. Opponents can NOT block you from scoring your own building types in this fashion, but once you have scored a type, you can not score that again. For expansion games, you can also score city buildings for coins (with building block multiplier) or land buildings for vps (with building block multiplier). Also for expansion games, after an 8.block building is built, a bonus tile can be placed on the player board. Every subsequent scoring will take into account the extra bonuses for that city or type. ''''Buying Objects'''' After each player's action, they have the option to puchase one of the 6 available objects on the main board (1 of each type) for 10 coins. If there are no remaining objects on the board, then no objects may be purchased. '''Ending the Game''' A player can CHOOSE to declare the game end if they successfully meet or exceed the requirements for the first 3 objectives. If they do so, they collect 5 vp for the declaration. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. If no one can or wants to declare the game end, the game ends when all 30 of the buildings on the main board have been built. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. '''Final Scoring''' Any object not included in the purple 'Object' objective is worth 1 vp. Coins are worth 1 vp for every 5 coins (unless you have the 'Top' brown objective that gives a different value). Each player will get vps for any objective cards that they match. Tiebreaker: The player with the most remaining purchased blocks, regardless of colour. b574bfc518e7b1577b6f6342faae5122dfa9fc01 1838 1837 2016-05-21T09:11:36Z Senatorhung 4176 wikitext text/x-wiki Link to english rules: https://dl.dropboxusercontent.com/u/720402/Palaces%20of%20Carrara.pdf '''Components''' There are a total of 42 blocks, 7 of each of 6 colours: white, yellow, red, green, blue, and black. There are a total of 30 buildings, in 6 different types, with block costs of 1, 2, 3, 4, and 5. For expansion games, there are an additional 6 buildings, with block costs of 8. They are separated into land (green-coloured) and city (gold-coloured): # villa (land): produces coat of arms objects # castle (land): produces flag objects # cathedral (city): produces cup objects # porta (city): produces gate objects # library (city): produces book objects # palaces (city): produces crown objects 5 of each of these types of objects can be acquired via scoring of cities. 1 of each type can ONLY be purchased for 10 coins from the board after a player's turn action. There are 6 cities on the board where buildings can be built. The buildings can only be built with a sufficient number of blocks that each city will accept. # Livornoa: only white blocks # Pisa: white or yellow blocks # Lucca: white, yellow, or red blocks # Viareggio: white, yellow, red, or green blocks # Massa: white, yellow, red, green, or blue blocks # Lerici: white, yellow, red, green, blue, or black blocks '''Standard vs. Expansion''' The 'standard' game should be considered as a learning setup only since the game becomes one of block buying efficiency. Here are the limitations in the standard game: # turning the block buying wheel is MANDATORY; # there is no separate scoring spot for land or city buildings; # 8.block buildings and their bonus scoring tiles are not available; # you can not upgrade existing buildings; AND # 3 fixed objectives. '''Objectives''' In an expansion game, there are 4 objective categories. There are 6 brown 'top' objectives, 8 purple 'object' objectives, 9 gray 'building' objectives, and 8 green 'bonus vps' objectives. In order for a player to declare the end of the game, they must meet the minimum requirements of the first 3 objectives. The fourth objective is only scored for bonus points at the end of the game. Some objectives are scaled for the number of players. Because of the number of objectives, and how they interact with each other, each game can require very different strategies, leading to excellent game replayability. '''Playing the Game''' Each turn, a player can do 1 of 3 things: # buy blocks; # build a building; OR # score a city or building type. ''''Buying Blocks'''' At the start of each game, there is 1 block of each colour in the first segment of the block wheel, with costs for each colour indicated on the outer rim. A player choosing to buy blocks may choose to turn the wheel one segment to decrease the cost before buying (this turn action is MANDATORY in the standard game). As the wheel is spun, each block becomes progressively cheaper by 1 coin, so that by the final segment, white blocks cost 1 coin, and every other block colour can be purchased for free. After the wheel is spun, a number of blocks are supplied to the first segment until the total number of blocks on the wheel is 11. If the wheel is NOT spun, no new blocks are supplied. Each player starts with 20 coins. After choosing to spin the wheel (or not), the active player can buy as many blocks from a single segment as they wish, as long as they have sufficient coins. Remember, spinning the wheel gives you access to cheaper blocks, but your opponents can also spin on their turns so any blocks you do not buy will get cheaper for them. If there are any blocks remaining in the final (cheapest) segment when the wheel is spun, they remain on the wheel and spin back into the 'first' segment. If, after spinning the wheel, a player does not have enough coins to buy ANY available block, they get 2 coins from the bank which ends their turn. If the wheel is empty and there are no blocks remaining in the supply, players must either build or score instead. ''''Building Buildings'''' Randomly selected, 9 of the 30 basic buildings are placed on the main board. For expansion games, the 6 8.block buildings are also made available beside the board. To build an available building, you first select the one you want, then click above the city (on your own player board) where you wish to build it. You then choose which blocks you wish to use to build the building, keeping in mind the block colour restrictions for each city. Blocks used to build in this way are returned to the supply. Another building from the supply (if available), is placed in the empty space on the main board. In expansion games, when you build an 8.block building, you can choose ANY 1 of the 8 bonus scoring tiles, regardless of the city that you built in or the building type. The ones for the cities of Livornoa, Pisa, and Lucca add +1 vp and +1 coin to the base scoring for each of those cities. The ones for the cities of Viareggio, Massa, and Lerici all add +1 vp to the base scoring for each of those cities. The ones for land and city buildings double the vps or coins received when using those scoring spaces. Also only in expansion games, you can upgrade an existing building in a city by paying the difference in block costs between the existing building and the more expensive new building (of any type) that you wish to put in its place. So, to upgrade a 1.block building to a 3.block building, you need to spend 2 blocks, keeping in mind the block colour restriction for the city. ''''Scoring'''' Each player starts with 6 scoring meeples. If you have used all 6 of your scoring meeples, you can no longer take the scoring action. To score a city, you must have sufficient buildings built in that city. For the cities of Livornoa, Pisa, and Lucca, only 2 buildings are required before those cities can be scored. For the cities of Viareggio, Massa, and Lerici, 3 buildings must be built before they can be scored. You can build more buildings in a city than the minimum before scoring that city, but each city can only be scored ONCE during the game. So, after one player scores a city, they place one of their scoring meeples on that city on the main board, and every other player is blocked from scoring that city. When a city is scored, each building in the city generates an object as long as there are objects of that type in the pool (excludes the 6 objects on the main board, which can only be purchased). As well, each scored city provides a separate bonus, either vps or coins (or both for expansion games after building an 8.block building), with the base score of the city multiplied by the number of blocks used to build the buildings in that city. *So, if you had the 1.block palace, 2.block castle, and 3.block library when you scored viareggio, you would collect 1 crown object, 1 flag object, and 1 book object, along with 1+2+3 (building blocks) * 2 (coins per block basic viareggio bonus) = 12 coins from the bank. Instead of scoring a city, you can choose to score one of the 6 building types, as long as you have built at least 1 of the buildings matching that type. Each building will provide the city score bonus that they are in (including block building multipliers), plus generate an object (if available). Place a scoring meeple on your board to match the type that you are scoring. Opponents can NOT block you from scoring your own building types in this fashion, but once you have scored a type, you can not score that again. For expansion games, you can also score city buildings for coins (with building block multiplier) or land buildings for vps (with building block multiplier). Also for expansion games, after an 8.block building is built, a bonus tile can be placed on the player board. Every subsequent scoring will take into account the extra bonuses for that city or type. ''''Buying Objects'''' After each player's action, they have the option to puchase one of the 6 available objects on the main board (1 of each type) for 10 coins. If there are no remaining objects on the board, then no objects may be purchased. '''Ending the Game''' A player can CHOOSE to declare the game end if they successfully meet or exceed the requirements for the first 3 objectives. If they do so, they collect 5 vp for the declaration. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. If no one can or wants to declare the game end, the game ends when all 30 of the buildings on the main board have been built. Each other player who has not yet played that turn (look to who has the first player marker) will get a final turn to act. '''Final Scoring''' Any object not included in the purple 'Object' objective is worth 1 vp (expansion games only). Coins are worth 1 vp for every 5 coins (unless you have the 'Top' brown objective that gives a different value). Each player will get vps for any objective cards that they match. Tiebreaker: The player with the most remaining purchased blocks, regardless of colour. f8431fd11a0e42bac27147fc90235a4ddc00032a Gamehelpfourcolorcards 0 218 1839 2016-05-21T12:00:53Z Lightknight 13104 I found this page done in the french version. wikitext text/x-wiki Four color cards is an traditional game that has no fixed set of rules (there are many popular variations). The version implemented on BGA is one of the most widely used rule on Taiwan, as described below. First, the players are dealt 20 cards, the first player has 1 more card and he/she must start by discarding. Then melds can be made with the card just discarded. Here are the possible melds: - General, adviser, and elephant can be melded to command meld. - Chariot, horseman, and cannon can be melded to field meld. - Different color soldiers can be melded to soldier meld ( 3 or 4 colors ). - Cards of the same type and color can be melded into pairs, triples or quadruples except generals and soldiers; the generals can go on their own and soldier can not meld into pairs. Scoring is as follows: - General = 1 point - Command = 2 points - Field = 1 point - pair = 0 points - triple = 1 / 3 points ( ground / hand ) - quadruple = 6 / 8 points ( ground / hand ) - quadruple of generals = 8 / 6 points ( ground / hand ) - 3 color soldiers = 3 points - 4 color soldiers = 5 points Players can make a triple (pong), quadruple (gan) or a win (hu) with no regards for the player order, but melds of other types can only be picked from the player before oneself. Choices for melds are made simultaneously by players, then priorities apply (strongest combination first, equalities decided by turn order). If a player can not or do not want to make a meld, he/she should draw a new card out to replace the discarded card (and start another melding phase). If a player makes a meld, he/she needs to discard one card from his/her hand. Generals can not be discarded. If the player can not discard, the round ends immediately and the points are scored. There is a extra chance to gain points by drawing a lucky card. If the player gets a card of the same type as one he/she already has, he/she get points depending on the number of cards of the same type. If the points are less than the target threshold to reach, which is 10, the player loses 10 points plus 1 base point to other players. If the treshold is reach or surpassed, the player earns the points in excess above the treshold plus base points from every other player. If the game ends by exhausting the deck, no one get points. Since the game is a gambling game, players start the game with a set amount of credits/money that will increase or decrease with the score of each successive round (three rounds by default). That's the story of the four color cards game. Enjoy! c20ca7bc9bde462a8dbbc0c02d0c3d5820436049 1840 1839 2016-05-21T14:57:31Z Oso 36 wikitext text/x-wiki Four color cards is an traditional game that has no fixed set of rules (there are many popular variations). The version implemented on BGA is one of the most widely used rule on Taiwan, as described below. First, the players are dealt 20 cards, the first player has 1 more card and he/she must start by discarding. Then melds can be made with the card just discarded. Here are the possible melds: - General, adviser, and elephant can be melded to command meld. - Chariot, horseman, and cannon can be melded to field meld. - Different color soldiers can be melded to soldier meld ( 3 or 4 colors ). - Cards of the same type and color can be melded into pairs, triples or quadruples except generals and soldiers; the generals can go on their<br>own and soldier can not meld into pairs. Scoring is as follows: - General = 1 point - Command = 2 points - Field = 1 point - pair = 0 points - triple = 1 / 3 points ( ground / hand ) - quadruple = 6 / 8 points ( ground / hand ) - quadruple of generals = 8 / 6 points ( ground / hand ) - 3 color soldiers = 3 points - 4 color soldiers = 5 points Players can make a triple (pong), quadruple (gan) or a win (hu) with no regards for the player order, but melds of other types can only be picked from the player before oneself. Choices for melds are made simultaneously by players, then priorities apply (strongest combination first, equalities decided by turn order). If a player can not or do not want to make a meld, he/she should draw a new card out to replace the discarded card (and start another melding phase). If a player makes a meld, he/she needs to discard one card from his/her hand. Generals can not be discarded. If the player can not discard, the round ends immediately and the points are scored. There is a extra chance to gain points by drawing a lucky card. If the player gets a card of the same type as one he/she already has, he/she get points depending on the number of cards of the same type. If the points are less than the target threshold to reach, which is 10, the player loses 10 points plus 1 base point to other players. If the treshold is reach or surpassed, the player earns the points in excess above the treshold plus base points from every other player. If the game ends by exhausting the deck, no one get points. Since the game is a gambling game, players start the game with a set amount of credits/money that will increase or decrease with the score of each successive round (three rounds by default). That's the story of the four color cards game. Enjoy! 9be735e4d3c9d21656b6e3b421f78fab1263dd0b 1851 1840 2016-06-05T18:03:08Z Xnedkx 13554 wikitext text/x-wiki Four color cards is an traditional game that has no fixed set of rules (there are many popular variations). The version implemented on BGA is one of the most widely used rule on Taiwan, as described below. First, the players are dealt 20 cards, the first player has 1 more card and he/she must start by discarding. Then melds can be made with the card just discarded. Here are the possible melds: - General, adviser, and elephant can be melded to command meld. - Chariot, horseman, and cannon can be melded to field meld. - Different color soldiers can be melded to soldier meld ( 3 or 4 colors ). - Cards of the same type and color can be melded into pairs, triples or quadruples except generals and soldiers; the generals can go on their<br>own and soldier can not meld into pairs. Scoring is as follows: - General = 1 point - Command = 2 points - Field = 1 point - pair = 0 points - triple = 1 / 3 points ( ground / hand ) - quadruple = 6 / 8 points ( ground / hand ) - quadruple of generals = 8 / 6 points ( ground / hand ) - 3 color soldiers = 3 points - 4 color soldiers = 5 points Players can make a triple (pong), quadruple (gan) or a win (hu) with no regards for the player order, but melds of other types can only be picked from the player before oneself. Choices for melds are made simultaneously by players, then priorities apply (strongest combination first, equalities decided by turn order). If a player can not or do not want to make a meld, he/she should draw a new card out to replace the discarded card (and start another melding phase). If a player makes a meld, he/she needs to discard one card from his/her hand. Generals can not be discarded. If the player can not discard, the round ends immediately and the points are scored. The combination priorities: ( equalities decided by turn order ) - Hu ( cards in hand + last discarded/drawn card are all able to become melds ) > - Gan ( quadruple ) / Pong ( triple ) > - Chi ( pair, command/field meld, 3/4 different color soldiers, or a lonely general ) There is a extra chance to gain points by drawing a lucky card. If the player gets a card of the same type as one he/she already has, he/she get points depending on the number of cards of the same type. If the points are less than the target threshold to reach, which is 10, the player loses 10 points plus 1 base point to other players. If the treshold is reach or surpassed, the player earns the points in excess above the treshold plus base points from every other player. If the game ends by exhausting the deck, no one get points. Since the game is a gambling game, players start the game with a set amount of credits/money that will increase or decrease with the score of each successive round (three rounds by default). That's the story of the four color cards game. Enjoy! 39946ef0a528ba0ee6975802a560280718fb3e50 Main game logic: yourgamename.game.php 0 86 1841 1765 2016-05-23T17:45:01Z Victoria la 11989 /* Player color preferences */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 79 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. Notifications sent between the game start (setupNewGame) and the end of the "action" method of the first active state will never reach their destination. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array. Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private data must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. Important: the variable for player name must be ${player_name} in order to be highlighted with the player color in the game log == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. == Player color preferences == BGA players (Club members) may now choose their preferred color for playing. For example, if they are used to play green for every board game, they can select "green" in their BGA preferences page. Making your game compatible with colors preferences is very easy and requires only 1 line of PHP and 1 configuration change : On your gameinfos.inc.php file, add the following lines : // Favorite colors support : if set to "true", support attribution of favorite colors based on player's preferences (see reattributeColorsBasedOnPreferences PHP method) 'favorite_colors_support' => true, Then, on your main <your_game>.game.php file, find the "reloadPlayersBasicInfos" call in your "setupNewGame" method and replace : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reloadPlayersBasicInfos(); By : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reattributeColorsBasedOnPreferences( $players, array( /* LIST HERE THE AVAILABLE COLORS OF YOUR GAME INSTEAD OF THESE ONES */"ff0000", "008000", "0000ff", "ffa500", "773300" ) ); self::reloadPlayersBasicInfos(); The "reattributeColorsBasedOnPreferences" method reattributes all colors, taking into account players color preferences and available colors. Note that you must update the colors to indicate the colors available for your game. 2 important remarks : * for some games (ex : Chess), the color has an influence on a mechanism of the game, most of the time by giving a special advantage to a player (ex : Starting the game). Color preference mechanism must NOT be used in such a case. * your logic should NEVER consider that the first player has the color X, that the second player has the color Y, and so on. If this is the case, your game will NOT be compatible with reattributeColorsBasedOnPreferences as this method attribute colors to players based on their preferences and not based as their order at the table. Colours currently listed as a choice in preferences: * #ff0000 Red * #008000 Green * #0000ff Blue * #ffa500 Yellow * #000000 Black * #ffffff White 8f34dd6b2e821d4ccf00deafbe61a96e0d7c9bd2 1846 1841 2016-05-31T12:02:34Z Victoria la 11989 /* Game states and active players */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 79 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails) : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. ; $this->gamestate->nextState( $state ) : Change current state to a new state, see [[Your game state machine: states.inc.php]] for more information about states ; $this->gamestate->state() : Get an associative array of current game state attributes, see [[Your game state machine: states.inc.php]] for state attributes $state=$this->gamestate->state(); if( $state['name'] == 'myGameState' ) {...} == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. Notifications sent between the game start (setupNewGame) and the end of the "action" method of the first active state will never reach their destination. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array. Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private data must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. Important: the variable for player name must be ${player_name} in order to be highlighted with the player color in the game log == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. == Player color preferences == BGA players (Club members) may now choose their preferred color for playing. For example, if they are used to play green for every board game, they can select "green" in their BGA preferences page. Making your game compatible with colors preferences is very easy and requires only 1 line of PHP and 1 configuration change : On your gameinfos.inc.php file, add the following lines : // Favorite colors support : if set to "true", support attribution of favorite colors based on player's preferences (see reattributeColorsBasedOnPreferences PHP method) 'favorite_colors_support' => true, Then, on your main <your_game>.game.php file, find the "reloadPlayersBasicInfos" call in your "setupNewGame" method and replace : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reloadPlayersBasicInfos(); By : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reattributeColorsBasedOnPreferences( $players, array( /* LIST HERE THE AVAILABLE COLORS OF YOUR GAME INSTEAD OF THESE ONES */"ff0000", "008000", "0000ff", "ffa500", "773300" ) ); self::reloadPlayersBasicInfos(); The "reattributeColorsBasedOnPreferences" method reattributes all colors, taking into account players color preferences and available colors. Note that you must update the colors to indicate the colors available for your game. 2 important remarks : * for some games (ex : Chess), the color has an influence on a mechanism of the game, most of the time by giving a special advantage to a player (ex : Starting the game). Color preference mechanism must NOT be used in such a case. * your logic should NEVER consider that the first player has the color X, that the second player has the color Y, and so on. If this is the case, your game will NOT be compatible with reattributeColorsBasedOnPreferences as this method attribute colors to players based on their preferences and not based as their order at the table. Colours currently listed as a choice in preferences: * #ff0000 Red * #008000 Green * #0000ff Blue * #ffa500 Yellow * #000000 Black * #ffffff White 722b3ee6e9a7c5bc83a4ccc2bebb3bee83a3a28c 1847 1846 2016-05-31T23:30:48Z Victoria la 11989 /* Game states and active players */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 79 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails). : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. ; $this->gamestate->nextState( $state ) : Change current state to a new state, see [[Your game state machine: states.inc.php]] for more information about states. ; $this->gamestate->state() : Get an associative array of current game state attributes, see [[Your game state machine: states.inc.php]] for state attributes. $state=$this->gamestate->state(); if( $state['name'] == 'myGameState' ) {...} == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. Notifications sent between the game start (setupNewGame) and the end of the "action" method of the first active state will never reach their destination. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array. Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private data must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. Important: the variable for player name must be ${player_name} in order to be highlighted with the player color in the game log == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. == Player color preferences == BGA players (Club members) may now choose their preferred color for playing. For example, if they are used to play green for every board game, they can select "green" in their BGA preferences page. Making your game compatible with colors preferences is very easy and requires only 1 line of PHP and 1 configuration change : On your gameinfos.inc.php file, add the following lines : // Favorite colors support : if set to "true", support attribution of favorite colors based on player's preferences (see reattributeColorsBasedOnPreferences PHP method) 'favorite_colors_support' => true, Then, on your main <your_game>.game.php file, find the "reloadPlayersBasicInfos" call in your "setupNewGame" method and replace : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reloadPlayersBasicInfos(); By : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reattributeColorsBasedOnPreferences( $players, array( /* LIST HERE THE AVAILABLE COLORS OF YOUR GAME INSTEAD OF THESE ONES */"ff0000", "008000", "0000ff", "ffa500", "773300" ) ); self::reloadPlayersBasicInfos(); The "reattributeColorsBasedOnPreferences" method reattributes all colors, taking into account players color preferences and available colors. Note that you must update the colors to indicate the colors available for your game. 2 important remarks : * for some games (ex : Chess), the color has an influence on a mechanism of the game, most of the time by giving a special advantage to a player (ex : Starting the game). Color preference mechanism must NOT be used in such a case. * your logic should NEVER consider that the first player has the color X, that the second player has the color Y, and so on. If this is the case, your game will NOT be compatible with reattributeColorsBasedOnPreferences as this method attribute colors to players based on their preferences and not based as their order at the table. Colours currently listed as a choice in preferences: * #ff0000 Red * #008000 Green * #0000ff Blue * #ffa500 Yellow * #000000 Black * #ffffff White 2225b1e8d21da0a1232c2144b5ddb1f9360002a0 1850 1847 2016-06-01T02:38:37Z Victoria la 11989 /* Game states and active players */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 79 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails). : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. ; $this->gamestate->nextState( $transition ) : Change current state to a new state. Important: parameter $transition is the name of the transition, and NOT the name of the target game state, see [[Your game state machine: states.inc.php]] for more information about states. ; $this->gamestate->state() : Get an associative array of current game state attributes, see [[Your game state machine: states.inc.php]] for state attributes. $state=$this->gamestate->state(); if( $state['name'] == 'myGameState' ) {...} == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. Notifications sent between the game start (setupNewGame) and the end of the "action" method of the first active state will never reach their destination. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array. Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private data must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. Important: the variable for player name must be ${player_name} in order to be highlighted with the player color in the game log == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. == Player color preferences == BGA players (Club members) may now choose their preferred color for playing. For example, if they are used to play green for every board game, they can select "green" in their BGA preferences page. Making your game compatible with colors preferences is very easy and requires only 1 line of PHP and 1 configuration change : On your gameinfos.inc.php file, add the following lines : // Favorite colors support : if set to "true", support attribution of favorite colors based on player's preferences (see reattributeColorsBasedOnPreferences PHP method) 'favorite_colors_support' => true, Then, on your main <your_game>.game.php file, find the "reloadPlayersBasicInfos" call in your "setupNewGame" method and replace : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reloadPlayersBasicInfos(); By : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reattributeColorsBasedOnPreferences( $players, array( /* LIST HERE THE AVAILABLE COLORS OF YOUR GAME INSTEAD OF THESE ONES */"ff0000", "008000", "0000ff", "ffa500", "773300" ) ); self::reloadPlayersBasicInfos(); The "reattributeColorsBasedOnPreferences" method reattributes all colors, taking into account players color preferences and available colors. Note that you must update the colors to indicate the colors available for your game. 2 important remarks : * for some games (ex : Chess), the color has an influence on a mechanism of the game, most of the time by giving a special advantage to a player (ex : Starting the game). Color preference mechanism must NOT be used in such a case. * your logic should NEVER consider that the first player has the color X, that the second player has the color Y, and so on. If this is the case, your game will NOT be compatible with reattributeColorsBasedOnPreferences as this method attribute colors to players based on their preferences and not based as their order at the table. Colours currently listed as a choice in preferences: * #ff0000 Red * #008000 Green * #0000ff Blue * #ffa500 Yellow * #000000 Black * #ffffff White 6cf77be5c90ebc6ad9f8a0303b62095b6d62a222 Gamehelppuertorico 0 23 1842 1085 2016-05-24T18:39:28Z Mr monster 13447 /* Rules summary */ wikitext text/x-wiki == Goal == Be the player with the most victory points at the end of the game by collecting: * victory points earned for buildings * victory point tokens earned at the captain phase * conditional victory points earned at the end of the game for occupied large buildings In case of a tie, the player owning the most doubloons and goods is the winner. == Rules summary == The game is played over several rounds. At the start of a round, the governor selects a role, then each player in turn selects a role. At the end of the round, the governor token moves to the next player. When a role has been chosen, each player in turn plays the action for this role. Only the player who selected the role can use the role privilege. Available roles are the following: * '''Mayor''': colonists set foot in the new world ! <br />''Privilege'': the mayor can get one more colonist from the supply. <br />''Action'': in turn, begining with the mayor, players get one colonist from the ship, until it is empty. Then players have to set colonists on their buildings and plantations. * '''Craftsman''': goods are produced. <br />''Privilege'': the craftsman can produce one more good of his choice. <br />''Action'': produce goods for your occupied buildings and plantations. * '''Trader''': goods are sold to the trading house. <br />''Privilege'': the trader earns 1 extra doubloon if he sells.<br />''Action'': sell one good the trading house doesn't have yet. * '''Settler''': plantations settlement. <br />''Privilege'': the settler can get a quarry instead of a plantation.<br />''Action'': get a plantation chosen among those available. * '''Builder''': buildings are bought and built. <br />Privilege: the builder can get a building for 1 doubloon less than the regular price. <br />Action: get a building chosen among those available. * '''Captain''': victory points are won by shipping goods to the old world. <br />''Privilege'': the captain earns one extra victory points if he ships some goods. <br />''Action'': select a type of good to load on a cargo ship; 1 victory point is earned for each barrel of this type of good loaded on the ship. * '''Prospector''': gold rush brings money! <br />''Privilege'': the prospector gets one doubloon from the bank. <br />''Action'': none. Please also note that occupied violet buildings have modifier effects for role actions. End of game happens at the end of the round for which one of the following events comes to pass: * there is not enough colonists in the supply to refill the colonist ship at the end of the mayor phase * the last victory point token has been earned during the captain phase * at least one of the players built on his 12th and last free space in the city. == Playing online == Choosing a role : click on the role of your choice in the list on the right of your game board. * Mayor role : accept or refuse to get an extra colonist from the supply. Colonists are then automatically recruited by players. Click on a building or a plantation to setup a colonist on it. Click on a colonist to send it back to San Juan (the counter for colonists in San Juan is situated in your player panel on the right of the page). * Craftsman role : goods production is automated (counters for goods owned are in the player panel on the right of the page). Then, choose one extra good that you can produce as your privilege. * Trader role : choose a good that you want to sell by clicking on the appropriate counter in your player panel. * Settler role : click on the plantation (or quarry) that you want. Placement on your board is automated. * Builder role : click on the building that you want to buy. Placement on your board is automated. * Captain role : click on the cargo boat on which you want to ship some goods. Then choose the type of good that you want to ship by clicking on the appropriate counter in your player panel. At the end of the captain phase, if you have some goods to store (warehouse or windrose), click on the corresponding counter. Stored goods will be highlighted by a red frame. * Prospector role : doubloon is earned immediately. Tooltips are available to give information on roles and buildings by hovering over game elements with the mouse. == 'Balanced game' variant == This variant implements two game balance fixes giving each player an equal chance of winning as listed in the [http://en.wikipedia.org/wiki/Puerto_Rico_%28board_game%29 Puerto Rico (board game) Wikipedia page]. * The prices of the Factory and University buildings are swapped so that the Factory costs 8 doubloons and the University costs 7 doubloons * Any player that starts with a corn plantation starts with 1 doubloon less than the players that start with an indigo plantation. == Two players variant == Craftsman Angst : if this variant is selected, players alternate selecting a role as usual, until the Governor has selected '''three''' roles and the opponent has selected '''two''' roles (instead of three in a classic two players game), then the governor token goes to the opponent and a new round starts. This variant avoids the consecutive selection of two roles by the same player which happens on a change of round with the classic two player game rules. This variant is described on [http://www.boardgamegeek.com/thread/679955/the-craftsman-angst-variant-the-most-popular-revis Board Game Geek]. '''Have a good game !''' a84f0191c386f0029c2e5180f8f0400c6a350b92 1843 1842 2016-05-24T18:40:35Z Mr monster 13447 /* Playing online */ wikitext text/x-wiki == Goal == Be the player with the most victory points at the end of the game by collecting: * victory points earned for buildings * victory point tokens earned at the captain phase * conditional victory points earned at the end of the game for occupied large buildings In case of a tie, the player owning the most doubloons and goods is the winner. == Rules summary == The game is played over several rounds. At the start of a round, the governor selects a role, then each player in turn selects a role. At the end of the round, the governor token moves to the next player. When a role has been chosen, each player in turn plays the action for this role. Only the player who selected the role can use the role privilege. Available roles are the following: * '''Mayor''': colonists set foot in the new world ! <br />''Privilege'': the mayor can get one more colonist from the supply. <br />''Action'': in turn, begining with the mayor, players get one colonist from the ship, until it is empty. Then players have to set colonists on their buildings and plantations. * '''Craftsman''': goods are produced. <br />''Privilege'': the craftsman can produce one more good of his choice. <br />''Action'': produce goods for your occupied buildings and plantations. * '''Trader''': goods are sold to the trading house. <br />''Privilege'': the trader earns 1 extra doubloon if he sells.<br />''Action'': sell one good the trading house doesn't have yet. * '''Settler''': plantations settlement. <br />''Privilege'': the settler can get a quarry instead of a plantation.<br />''Action'': get a plantation chosen among those available. * '''Builder''': buildings are bought and built. <br />Privilege: the builder can get a building for 1 doubloon less than the regular price. <br />Action: get a building chosen among those available. * '''Captain''': victory points are won by shipping goods to the old world. <br />''Privilege'': the captain earns one extra victory points if he ships some goods. <br />''Action'': select a type of good to load on a cargo ship; 1 victory point is earned for each barrel of this type of good loaded on the ship. * '''Prospector''': gold rush brings money! <br />''Privilege'': the prospector gets one doubloon from the bank. <br />''Action'': none. Please also note that occupied violet buildings have modifier effects for role actions. End of game happens at the end of the round for which one of the following events comes to pass: * there is not enough colonists in the supply to refill the colonist ship at the end of the mayor phase * the last victory point token has been earned during the captain phase * at least one of the players built on his 12th and last free space in the city. == Playing online == Choosing a role : click on the role of your choice in the list on the right of your game board. * '''Mayor''': accept or refuse to get an extra colonist from the supply. Colonists are then automatically recruited by players. Click on a building or a plantation to setup a colonist on it. Click on a colonist to send it back to San Juan (the counter for colonists in San Juan is situated in your player panel on the right of the page). * '''Craftsman''': goods production is automated (counters for goods owned are in the player panel on the right of the page). Then, choose one extra good that you can produce as your privilege. * '''Trader''': choose a good that you want to sell by clicking on the appropriate counter in your player panel. * '''Settler''': click on the plantation (or quarry) that you want. Placement on your board is automated. * '''Builder''': click on the building that you want to buy. Placement on your board is automated. * '''Captain''': click on the cargo boat on which you want to ship some goods. Then choose the type of good that you want to ship by clicking on the appropriate counter in your player panel. At the end of the captain phase, if you have some goods to store (warehouse or windrose), click on the corresponding counter. Stored goods will be highlighted by a red frame. * '''Prospector''': doubloon is earned immediately. Tooltips are available to give information on roles and buildings by hovering over game elements with the mouse. == 'Balanced game' variant == This variant implements two game balance fixes giving each player an equal chance of winning as listed in the [http://en.wikipedia.org/wiki/Puerto_Rico_%28board_game%29 Puerto Rico (board game) Wikipedia page]. * The prices of the Factory and University buildings are swapped so that the Factory costs 8 doubloons and the University costs 7 doubloons * Any player that starts with a corn plantation starts with 1 doubloon less than the players that start with an indigo plantation. == Two players variant == Craftsman Angst : if this variant is selected, players alternate selecting a role as usual, until the Governor has selected '''three''' roles and the opponent has selected '''two''' roles (instead of three in a classic two players game), then the governor token goes to the opponent and a new round starts. This variant avoids the consecutive selection of two roles by the same player which happens on a change of round with the classic two player game rules. This variant is described on [http://www.boardgamegeek.com/thread/679955/the-craftsman-angst-variant-the-most-popular-revis Board Game Geek]. '''Have a good game !''' 630da748787c69b762be67441834ec254a8e5209 Reputation 0 17 1844 1604 2016-05-26T15:22:46Z Mopie 10416 /* Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png */ wikitext text/x-wiki [[Category:Help]] == What is reputation ? == On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance. To achieve this goal, each player has a '''reputation profile''' which is the representation of his general attitude with others players. This profile is composed of 3 items: * Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png) * % of games you finished * % of games you finished with no clock penalties Seeing the reputation profile of a player, you are able to check if his behavior is good, if he won't quit the game before the end, and if he respect time limits. == How to increase my reputation / what makes my reputation decrease ? == At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks. * a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player. * a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player. You can only give a single thumb (green or red) to a single player. If your opinion changes you can click again on a thumb to reflect this change. As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended you leave the game or expel this player. By nature, opinions are subjective. There is nothing we can do for you if you receive a "red thumb" for an unfair reason. However, we know by experience that this system has a lot of advantages and generally gives relevant and useful information. == Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png == * Be polite! Say at least "hello" and "good luck" at the beginning of the game, and maybe "good game" ("gg") at the end of the game. * When you need some time to think, click on "I would like to think a little" link. * Always stay calm: it's a game. * Don't press your opponent to play if he or she has some time left. * If you really can't finish the game (this is not supposed to happen...), then say you are sorry and leave the game (don't wait to get expelled) to save your opponents time. Voluntarily disconnecting and conceding victory to the opponent does not cost you reputation like being expelled does. * Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give them a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!). * Be a good winner: if your opponent makes a mistake you can signal it to them, but avoid triumphalism and provocation. == What are the consequences of a bad reputation ? == A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you. It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents. 5619606baa6edcedb225051d86a495d9ea91485d 1845 1844 2016-05-26T15:24:12Z Mopie 10416 /* What is reputation ? */ wikitext text/x-wiki [[Category:Help]] == What is reputation ? == On '''Board Game Arena''', we would like to have a strong competitive atmosphere with a respectful and fair play ambiance. To achieve this goal, each player has a '''reputation profile''' which is the representation of their general attitude with others players. This profile is composed of 3 items: * Opinions from other players (http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png) * % of games you finished * % of games you finished with no clock penalties Seeing the reputation profile of a player, you are able to check if their behavior is good, if they are unlikely to quit the game before the end, and if they respect time limits. == How to increase my reputation / what makes my reputation decrease ? == At any time, you can give others players http://fr.boardgamearena.com/theme/img/common/reputation_up.png and http://fr.boardgamearena.com/theme/img/common/reputation_down.png marks. * a http://fr.boardgamearena.com/theme/img/common/reputation_up.png if you liked to play with him/her, and recommend to play with this player. * a http://fr.boardgamearena.com/theme/img/common/reputation_down.png if you disliked to play with him/her, and discourage others to play with this player. You can only give a single thumb (green or red) to a single player. If your opinion changes you can click again on a thumb to reflect this change. As soon as you give a "red thumb" to a player, a warning message is displayed when you try to join a table where this player is. In this situation it is recommended you leave the game or expel this player. By nature, opinions are subjective. There is nothing we can do for you if you receive a "red thumb" for an unfair reason. However, we know by experience that this system has a lot of advantages and generally gives relevant and useful information. == Advice: how to get plenty of http://fr.boardgamearena.com/theme/img/common/reputation_up.png == * Be polite! Say at least "hello" and "good luck" at the beginning of the game, and maybe "good game" ("gg") at the end of the game. * When you need some time to think, click on "I would like to think a little" link. * Always stay calm: it's a game. * Don't press your opponent to play if he or she has some time left. * If you really can't finish the game (this is not supposed to happen...), then say you are sorry and leave the game (don't wait to get expelled) to save your opponents time. Voluntarily disconnecting and conceding victory to the opponent does not cost you reputation like being expelled does. * Be a good loser: if your lose because of bad luck or a strategy you dislike, don't blame the luck or your opponent (and don't give them a http://fr.boardgamearena.com/theme/img/common/reputation_down.png for this reason!). * Be a good winner: if your opponent makes a mistake you can signal it to them, but avoid triumphalism and provocation. == What are the consequences of a bad reputation ? == A bad reputation makes you suspect to your potential opponents. You will have to explain your situation, and maybe some players won't take the risk to play with you. It is also possible to filter players by reputation on a table. The worse your reputation is, the bigger difficulties you will have to find opponents. 448875fd15389859ec3f2072ec3344987bf3be7b Main game logic: yourgamename.game.php 0 86 1852 1850 2016-06-06T00:14:26Z Victoria la 11989 Debugging wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; function getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. <pre> self::getObjectFromDB( "SELECT player_name name, player_color color FROM player WHERE player_id='1234'" ); Result: array( 'id' => 1234, 'name' => 'myuser1', 'color' => 'ff0000' ) </pre> Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 79 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails). : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. ; $this->gamestate->nextState( $transition ) : Change current state to a new state. Important: parameter $transition is the name of the transition, and NOT the name of the target game state, see [[Your game state machine: states.inc.php]] for more information about states. ; $this->gamestate->state() : Get an associative array of current game state attributes, see [[Your game state machine: states.inc.php]] for state attributes. $state=$this->gamestate->state(); if( $state['name'] == 'myGameState' ) {...} == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. Notifications sent between the game start (setupNewGame) and the end of the "action" method of the first active state will never reach their destination. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array. Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private data must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. Important: the variable for player name must be ${player_name} in order to be highlighted with the player color in the game log == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. == Player color preferences == BGA players (Club members) may now choose their preferred color for playing. For example, if they are used to play green for every board game, they can select "green" in their BGA preferences page. Making your game compatible with colors preferences is very easy and requires only 1 line of PHP and 1 configuration change : On your gameinfos.inc.php file, add the following lines : // Favorite colors support : if set to "true", support attribution of favorite colors based on player's preferences (see reattributeColorsBasedOnPreferences PHP method) 'favorite_colors_support' => true, Then, on your main <your_game>.game.php file, find the "reloadPlayersBasicInfos" call in your "setupNewGame" method and replace : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reloadPlayersBasicInfos(); By : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reattributeColorsBasedOnPreferences( $players, array( /* LIST HERE THE AVAILABLE COLORS OF YOUR GAME INSTEAD OF THESE ONES */"ff0000", "008000", "0000ff", "ffa500", "773300" ) ); self::reloadPlayersBasicInfos(); The "reattributeColorsBasedOnPreferences" method reattributes all colors, taking into account players color preferences and available colors. Note that you must update the colors to indicate the colors available for your game. 2 important remarks : * for some games (ex : Chess), the color has an influence on a mechanism of the game, most of the time by giving a special advantage to a player (ex : Starting the game). Color preference mechanism must NOT be used in such a case. * your logic should NEVER consider that the first player has the color X, that the second player has the color Y, and so on. If this is the case, your game will NOT be compatible with reattributeColorsBasedOnPreferences as this method attribute colors to players based on their preferences and not based as their order at the table. Colours currently listed as a choice in preferences: * #ff0000 Red * #008000 Green * #0000ff Blue * #ffa500 Yellow * #000000 Black * #ffffff White == Debugging and Tracing == To debug php code you can use some tracing functions available from the parent class such as debug, trace, error, warn, dump. self::debug("Ahh!"); self::dump('my_var',$my_var); See [[Practical_debugging]] section for complete information about debugging interfaces and where to find logs. 5c8c51d8cba0dee084246421ca03ed33cc0fb1dd 1873 1852 2016-06-19T16:12:36Z Victoria la 11989 /* Accessing database */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. : Note: if you using standard types in ajax actions, like AT_alphanum it is sanitized before arrival, : this is only needed if you manage to get unchecked string, like in the games where user has to enter text as a response. <pre> </pre> Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 79 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails). : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. ; $this->gamestate->nextState( $transition ) : Change current state to a new state. Important: parameter $transition is the name of the transition, and NOT the name of the target game state, see [[Your game state machine: states.inc.php]] for more information about states. ; $this->gamestate->state() : Get an associative array of current game state attributes, see [[Your game state machine: states.inc.php]] for state attributes. $state=$this->gamestate->state(); if( $state['name'] == 'myGameState' ) {...} == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. Notifications sent between the game start (setupNewGame) and the end of the "action" method of the first active state will never reach their destination. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array. Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private data must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. Important: the variable for player name must be ${player_name} in order to be highlighted with the player color in the game log == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. 'table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. 'name' is the name of your statistics, as it has been defined in your stats.inc.php file. 'value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "player_id" argument, the value is set for ALL players. '''function setStat( $value, $name, $player_id = null )''' Set a statistic value. If "player_id" is not specified, setStat consider it is a TABLE statistic. If "player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value. Same behavior as above. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. == Player color preferences == BGA players (Club members) may now choose their preferred color for playing. For example, if they are used to play green for every board game, they can select "green" in their BGA preferences page. Making your game compatible with colors preferences is very easy and requires only 1 line of PHP and 1 configuration change : On your gameinfos.inc.php file, add the following lines : // Favorite colors support : if set to "true", support attribution of favorite colors based on player's preferences (see reattributeColorsBasedOnPreferences PHP method) 'favorite_colors_support' => true, Then, on your main <your_game>.game.php file, find the "reloadPlayersBasicInfos" call in your "setupNewGame" method and replace : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reloadPlayersBasicInfos(); By : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reattributeColorsBasedOnPreferences( $players, array( /* LIST HERE THE AVAILABLE COLORS OF YOUR GAME INSTEAD OF THESE ONES */"ff0000", "008000", "0000ff", "ffa500", "773300" ) ); self::reloadPlayersBasicInfos(); The "reattributeColorsBasedOnPreferences" method reattributes all colors, taking into account players color preferences and available colors. Note that you must update the colors to indicate the colors available for your game. 2 important remarks : * for some games (ex : Chess), the color has an influence on a mechanism of the game, most of the time by giving a special advantage to a player (ex : Starting the game). Color preference mechanism must NOT be used in such a case. * your logic should NEVER consider that the first player has the color X, that the second player has the color Y, and so on. If this is the case, your game will NOT be compatible with reattributeColorsBasedOnPreferences as this method attribute colors to players based on their preferences and not based as their order at the table. Colours currently listed as a choice in preferences: * #ff0000 Red * #008000 Green * #0000ff Blue * #ffa500 Yellow * #000000 Black * #ffffff White == Debugging and Tracing == To debug php code you can use some tracing functions available from the parent class such as debug, trace, error, warn, dump. self::debug("Ahh!"); self::dump('my_var',$my_var); See [[Practical_debugging]] section for complete information about debugging interfaces and where to find logs. f696bae1d79d735b02a149df97411f7f9121613b Gamehelpfourcolorcards 0 218 1853 1851 2016-06-06T03:03:41Z Xnedkx 13554 wikitext text/x-wiki Four color cards is an traditional game that has no fixed set of rules (there are many popular variations). The version implemented on BGA is one of the most widely used rule on Taiwan, as described below. First, the players are dealt 20 cards, the first player has 1 more card and he/she must start by discarding. Then melds can be made with the card just discarded. Here are the possible melds: - General, adviser, and elephant can be melded to command meld. - Chariot, horseman, and cannon can be melded to field meld. - Different color soldiers can be melded to soldier meld ( 3 or 4 colors ). - Cards of the same type and color can be melded into pairs, triples or quadruples except generals and soldiers; the generals can go on their<br>own and soldier can not meld into pairs. Scoring is as follows: - General = 1 point - Command = 2 points - Field = 1 point - pair = 0 points - triple = 1 / 3 points ( ground / hand ) - quadruple = 6 / 8 points ( ground / hand ) - quadruple of generals = 8 / 6 points ( ground / hand ) - 3 color soldiers = 3 points - 4 color soldiers = 5 points Players can make a triple (pong), quadruple (gan) or a win (hu) with no regards for the player order, but melds of other types can only be picked from the player before oneself. Choices for melds are made simultaneously by players, then priorities apply (strongest combination first, equalities decided by turn order). If a player can not or do not want to make a meld, he/she should draw a new card out to replace the discarded card (and start another melding phase). If a player makes a meld, he/she needs to discard one card from his/her hand. Generals can not be discarded. If the player can not discard, the round ends immediately and the points are scored. The combination priorities are listed below: ( equalities decided by turn order ) - Hu ( cards in hand + last discarded/drawn card are all able to become melds ) > - Gan ( quadruple ) / Pong ( triple ) > - Chi ( pair, command/field meld, 3/4 different color soldiers, or a lonely general ) There is a extra chance to gain points by drawing a lucky card. If the player gets a card of the same type as one he/she already has, he/she get points depending on the number of cards of the same type. If the points are less than the target threshold to reach, which is 10, the player loses 10 points plus 1 base point to other players. If the treshold is reach or surpassed, the player earns the points in excess above the treshold plus base points from every other player. If the game ends by exhausting the deck, no one get points. Since the game is a gambling game, players start the game with a set amount of credits/money that will increase or decrease with the score of each successive round (three rounds by default). That's the story of the four color cards game. Enjoy! e7072a6b4ae206532a5c69b39ccc871ecf48b848 1855 1853 2016-06-09T01:29:32Z Xnedkx 13554 wikitext text/x-wiki Four color cards is an traditional game that has no fixed set of rules (there are many popular variations). The version implemented on BGA is one of the most widely used rule on Taiwan, as described below. First, the players are dealt 20 cards, the first player has 1 more card and he/she must start by discarding. Then melds can be made with the card just discarded. Here are the possible melds: - General, adviser, and elephant can be melded to command meld. - Chariot, horseman, and cannon can be melded to field meld. - Different color soldiers can be melded to soldier meld ( 3 or 4 colors ). - Cards of the same type and color can be melded into pairs, triples or quadruples except generals and soldiers; the generals can go on their<br>own and soldier can not meld into pairs. Scoring is as follows: - General = 1 point - Command = 2 points - Field = 1 point - pair = 0 points - triple = 1 / 3 points ( ground / hand ) - quadruple = 6 / 8 points ( ground / hand ) - quadruple of generals = 8 / 6 points ( ground / hand ) - 3 color soldiers = 3 points - 4 color soldiers = 5 points Players can make a triple (pong), quadruple (gan) or a win (hu) with no regards for the player order, but melds of other types can only be picked from the player before oneself. Choices for melds are made simultaneously by players, then priorities apply (strongest combination first, equalities decided by turn order). If a player can not or do not want to make a meld, he/she should draw a new card out to replace the discarded card (and start another melding phase). If a player makes a meld, he/she needs to discard one card from his/her hand. Generals can not be discarded. If the player can not discard, the round ends immediately and the points are scored. The combination priorities are listed below: ( equalities decided by turn order ) - Hu ( cards in hand + last discarded/drawn card are all able to become melds ) > - Gan ( quadruple ) / Pong ( triple ) > - Chi ( pair, command/field meld, 3/4 different color soldiers, or a lonely general ) There is a extra chance to gain points by drawing a lucky card. If the player gets a card of the same type as one he/she already has, he/she get points depending on the number of cards of the same type. If the points are less than the target threshold to reach, which is 10, the player loses 10 points plus 1 base point to other players. If the threshold is reach or surpassed, the player earns the points in excess above the treshold plus base points from every other player. If the game ends by exhausting the deck, no one get points. Since the game is a gambling game, players start the game with a set amount of credits/money that will increase or decrease with the score of each successive round (three rounds by default). That's the story of the four color cards game. Enjoy! 5ba5b27ad61847c011f8635268ce525b2d1310d1 1856 1855 2016-06-09T01:30:39Z Xnedkx 13554 wikitext text/x-wiki Four color cards is an traditional game that has no fixed set of rules (there are many popular variations). The version implemented on BGA is one of the most widely used rule on Taiwan, as described below. First, the players are dealt 20 cards, the first player has 1 more card and he/she must start by discarding. Then melds can be made with the card just discarded. Here are the possible melds: - General, adviser, and elephant can be melded to command meld. - Chariot, horseman, and cannon can be melded to field meld. - Different color soldiers can be melded to soldier meld ( 3 or 4 colors ). - Cards of the same type and color can be melded into pairs, triples or quadruples except generals and soldiers; the generals can go on their<br>own and soldier can not meld into pairs. Scoring is as follows: - General = 1 point - Command = 2 points - Field = 1 point - pair = 0 points - triple = 1 / 3 points ( ground / hand ) - quadruple = 6 / 8 points ( ground / hand ) - quadruple of generals = 8 / 6 points ( ground / hand ) - 3 color soldiers = 3 points - 4 color soldiers = 5 points Players can make a triple (pong), quadruple (gan) or a win (hu) with no regards for the player order, but melds of other types can only be picked from the player before oneself. Choices for melds are made simultaneously by players, then priorities apply (strongest combination first, equalities decided by turn order). If a player can not or do not want to make a meld, he/she should draw a new card out to replace the discarded card (and start another melding phase). If a player makes a meld, he/she needs to discard one card from his/her hand. Generals can not be discarded. If the player can not discard, the round ends immediately and the points are scored. The combination priorities are listed below: ( equalities decided by turn order ) - Hu ( cards in hand + last discarded/drawn card are all able to become melds ) > - Gan ( quadruple ) / Pong ( triple ) > - Chi ( pair, command/field meld, 3/4 different color soldiers, or a lonely general ) There is a extra chance to gain points by drawing a lucky card. If the player gets a card of the same type as one he/she already has, he/she get points depending on the number of cards of the same type. If the points are less than the target threshold to reach, which is 10, the player loses 10 points plus 1 base point to other players. If the threshold is reached or surpassed, the player earns the points in excess above the threshold plus base points from every other player. If the game ends by exhausting the deck, no one get points. Since the game is a gambling game, players start the game with a set amount of credits/money that will increase or decrease with the score of each successive round (three rounds by default). That's the story of the four color cards game. Enjoy! 3015399b767dbb172ec36d634accccec6f55229d 1863 1856 2016-06-17T15:31:01Z Xnedkx 13554 wikitext text/x-wiki ==Introduction== Four color cards is an traditional game that has no fixed set of rules (there are many popular variations). The version implemented on BGA is one of the most widely used rule on Taiwan, as described below. The cards have 4 colors in red, green, yellow, and white with 7 types ( General, Adviser, Elephant, Chariot, Horseman, Cannon, and Soldier ). There are 4 pieces of each, that's 4 × 7 × 4 = 112 cards. It is 2 to 4 players game. The players take turns to draw a card from the deck or to make a meld and discard a hand card - there are other melding chances that do not follow the player order - until a player calls "hu" and finishes the round. If the player points of finisher's melds reaches the threshold, the player wins scores from others, else the player loses points to others. ==Game Rules== First, the players are dealt 20 cards, the first player has 1 more card and he/she must start by discarding. Then melds can be made with the card just discarded. Here are the possible melds: - General, adviser, and elephant can be melded to command meld. - Chariot, horseman, and cannon can be melded to field meld. - Different color soldiers can be melded to soldier meld ( 3 or 4 colors ). - Cards of the same type and color can be melded into pairs, triples or quadruples except generals and soldiers;<br>the generals can go on their own and soldiers can not meld into pairs. Scoring is as follows: - General = 1 point - Command = 2 points - Field = 1 point - pair = 0 points - triple = 1 / 3 points ( ground / hand ) - quadruple = 6 / 8 points ( ground / hand ) - quadruple of generals = 8 / 6 points ( ground / hand ) - 3 color soldiers = 3 points - 4 color soldiers = 5 points Players can make a triple (pong), quadruple (gan) or a win (hu) with no regards for the player order, but melds of other types can only be picked from the player before oneself. Choices for melds are made simultaneously by players, then priorities apply (strongest combination first, equalities decided by turn order). If a player can not or do not want to make a meld, he/she should draw a new card out to replace the discarded card (and start another melding phase which he/she have the melding chance with). If a player makes a meld, he/she needs to discard one card from his/her hand. Generals can not be discarded. If the player can not discard, the round ends immediately and the points are scored. If a player's hand cards are all able to become melds after making a meld, he/she can call "hu" to make the meld and finishes the round. The combination priorities are listed below: ( equalities decided by turn order ) - hu ( cards in hand + last discarded/drawn card are all able to become melds ) > - gan ( quadruple ) / pong ( triple ) > - chi ( pair, command/field meld, 3/4 different color soldiers, or a lonely general ) There is a extra chance to gain points by drawing a lucky card. If the player gets a card of the same type as one he/she already has, he/she get points depending on the number of cards of the same type. If the points are less than the target threshold to reach, which is 10, the player loses 10 points plus 1 base point to other players. If the threshold is reached or surpassed, the player earns the points in excess above the threshold plus base points from every other player. If the game ends by exhausting the deck, no one get points. Since the game is a gambling game, players start the game with a set amount of credits/money that will increase or decrease with the score of each successive round (three rounds by default). That's the story of the four color cards game. Enjoy! 386cffa497391c4bb3c96909186f9c9b0d8894b7 1864 1863 2016-06-18T01:36:14Z Xnedkx 13554 wikitext text/x-wiki ==Introduction== Four color cards is an traditional game that has no fixed set of rules (there are many popular variations). The version implemented on BGA is one of the most widely used rule on Taiwan, as described below. The cards have 4 colors in red, green, yellow, and white with 7 types ( General, Adviser, Elephant, Chariot, Horseman, Cannon, and Soldier ). There are 4 pieces of each, that's 4 × 7 × 4 = 112 cards. Four color cards is 2 to 4 players game. The players take turns to make a meld and discard a hand card - there are other melding chances that do not follow the player order - or to draw a card from the deck until a player calls "hu" and finishes the round. If the points of finisher's melds reaches the threshold, the player wins scores from others, else the player loses points to others. ==Game Rules== First, the players are dealt 20 cards, the first player has 1 more card and he/she must start by discarding. Then melds can be made with the card just discarded. Here are the possible melds: - General, adviser, and elephant can be melded to command meld. - Chariot, horseman, and cannon can be melded to field meld. - Different color soldiers can be melded to soldier meld ( 3 or 4 colors ). - Cards of the same type and color can be melded into pairs, triples or quadruples except generals and soldiers;<br>the generals can go on their own and soldiers can not meld into pairs. Scoring is as follows: - General = 1 point - Command = 2 points - Field = 1 point - pair = 0 points - triple = 1 / 3 points ( ground / hand ) - quadruple = 6 / 8 points ( ground / hand ) - quadruple of generals = 8 / 6 points ( ground / hand ) - 3 color soldiers = 3 points - 4 color soldiers = 5 points Players can make a triple (pong), quadruple (gan) or a win (hu) with no regards for the player order, but melds of other types can only be picked from the player before oneself. Choices for melds are made simultaneously by players, then priorities apply (strongest combination first, equalities decided by turn order). If a player can not or do not want to make a meld, he/she should draw a new card out to replace the discarded card (and start another melding phase which he/she have the melding chance with). If a player makes a meld, he/she needs to discard one card from his/her hand. Generals can not be discarded. If the player can not discard, the round ends immediately and the points are scored. If a player's hand cards are all able to become melds after making a meld, he/she can call "hu" to make the meld and finishes the round. The combination priorities are listed below: ( equalities decided by turn order ) - hu ( cards in hand + last discarded/drawn card are all able to become melds ) > - gan ( quadruple ) / pong ( triple ) > - chi ( pair, command/field meld, 3/4 different color soldiers, or a lonely general ) There is a extra chance to gain points by drawing a lucky card. If the player gets a card of the same type as one he/she already has, he/she get points depending on the number of cards of the same type. If the points are less than the target threshold to reach, which is 10, the player loses 10 points plus 1 base point to other players. If the threshold is reached or surpassed, the player earns the points in excess above the threshold plus base points from every other player. If the game ends by exhausting the deck, no one get points. Since the game is a gambling game, players start the game with a set amount of credits/money that will increase or decrease with the score of each successive round (three rounds by default). That's the story of the four color cards game. Enjoy! e7ce099069d99a68494aac0addf980f43eb1f712 Tools and tips of BGA Studio 0 99 1854 774 2016-06-07T12:10:34Z Victoria la 11989 /* Run from the chat */ wikitext text/x-wiki == Starting a game in one click == To start a game: * Create a new table with your game. * If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table. * Click on "Express Start". == Stopping a game in one click == * Click on the "quit" icon on the top right of the screen. * Click on "Express Stop". == Switching between users == when running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective. == Access to game database == Immediately at the bottom of the game area, the "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game. == Save & restore state == Using links of this section, you can save the complete current (database) state of your game, then restore it later. This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine. We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations. Limits: * the "restore" function does not work anymore when the game is over. * a saved situation from a given table cannot be restored in another table. * when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually. == Input/Output debugging section == This section shows you: * The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">" * The notifications received by your game interface. Notifications (inputs) begins with "<". Note: if you click on some notification title, you can resend it immediately to the user interface. == Run PHP functions from the chat == On BGA Studio, you can directly run a PHP method from the table chat. For example, if on your PHP you have this method: function giveMoneyToPlayer($player_id, $amount) { ... } You can call this method directly from the chat like this: giveMoneyToPlayer(2564,2) Note: this is not a real php statement, you cannot use self::, you cannot use ";" at the end and you cannot use quotes, if you need to pass a string skip the quotes, like this giveToActivePlayer(money,2) == Dev Tips == '''Edit TPL''' <p> To edit TPL with HTML code highlightings in Gedit under Ubuntu: find gtksourceview directory in /usr/share, depending on your version (2.0, 3.0,...). <br> Here it's 3.0, then type in a terminal window: <pre> sudo gedit /usr/share/gtksourceview-3.0/language-specs/html.lang </pre> then find 'globs' section, and change: <pre> <property name="globs">*.html;*.htm;*.tpl</property> </pre> a776ae63dd5aafca839b9d8259c56f487ecd61a0 Gamehelptokaido 0 134 1857 1303 2016-06-09T22:32:34Z Rnietzsche 12483 wikitext text/x-wiki ==  Objective of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' ===Encounters=== :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - Pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object and 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. ===Farm=== :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X= Loses coins, 1= Recovers coins, 2/3/3/4= Gains double that many coins). ===Hot Springs=== :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4 points (counts for ''Bather'' accomplishment). ===Panorama=== :('''B''') There are three Panorama types and are made of 3 (Field), 4 (Mountain), or 5 (Paddy) sections. : When a player stops on a Panorama they take the first Panorama of that type that they do not have (value from 1-5) and scores that many points. Each traveler can create only a single panorama of each type and when completed can no longer stop on the spaces corresponding to that type. :('''E''') A player may instead take a Cherry Tree and gain 2 points and 1 coin. (''There are 6 Cherry Tree cards.'') ===Temple=== :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn points. ===Village=== :('''B''') The player draws 3 Souvenir cards and can purchase 1-3 of these cards for 1-3 coins. There are four different Souvenirs and are grouped in sets. The first Souvenir in each set is worth 1 point, the next is 3 points, then 5 and 7 points. :('''E''') Acquire a Legendary Object (counts for ''Collector'' accomplishment) for 1-3 coins: :* Shodo & Emaki - For 1 coin, gain 1 point for each Souvenir or Legendary Object. Gain 1 point for each Souvenir thereafter. :* Buppatsu & Ema - For 2 coins this counts as a different Souvenir type, 5 types in a set is worth 9 points. :* Murasame & Masamune - For 3 coins, gain 8 points. ===Inns=== : All Travelers must stop at each Inn, they may not leave until all players have arrived at that Inn. : The Inns allow players to buy one unique Meal card for 1-3 coins that are worth 6 points. : When the first traveler arrives at an Inn, they draw as many Meal cards as there are players, plus 1. : As players arrive at the Inn they may buy a Meal card to add to their collection, hidden from other players. :* ''A traveler cannot taste the same culinary specialty twice during their journey.'' :* ''A traveler can never purchase more than one Meal card per Inn.'' :* ''A traveler is never obliged to purchase a Meal card.'' == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. == Travelers == === Base Game=== * Chuubei - Starting coins - 4 - At intermediate inns, draws encounter card * Kinko - Starting coins - 7 - At inns, buys meals at 1 coin discount * Hiroshige - Starting coins - 3 - At intermediate inns, acquires panorama card of choice * Yoshiyasu - Starting coins - 9 - At encounters, draws two encounter cards and keeps one; places other on bottom of deck * Satsuki - Starting coins - 2 - At inns, selects one meal card at random from the set of meal cards; may take it for free or purchase another at full price * Mitsukuni - Starting coins - 6 - Earns 1 additional point per hot spring and achievement card * Sasayakko - Starting coins - 5 - At villages, when purchasing at least two souvenirs, the cheapest is free; must have enough coins to pay for both at full price * Hirotada - Starting coins - 8 - At temples, may take 1 coin from the bank and donate it to the temple, scoring 1 point; does this in addition to normal temple action * Umegae - Starting coins - 5 - At encounters, gains 1 coin and 1 point before drawing encounter card * Zen-emon - Starting coins - 6 - At villages, may purchase one souvenir for 1 coin instead of full price == Game Options == === Initiation === A simplified version with no Travelers and everyone starting with 7 coins. === Return Trip === Instead of starting on the left side of the board, players move right to left. === Gastronomy === The first person arriving at an Inn draws one less card, only drawing one card per player. === Preparations === When leaving the starting Inn, the last player gains two coins, the next gains one coin, the fourth and fifth players each lose a coin. === Crossroads === This expansion adds a second option at each location (other than the Inns) to choose from when stopping. === New Encounters === This adds 4 new encounters to the possibilities when on the 'Encounters' space. 8030bf01620a3f597b43b2b6bb6e3acc6846143c 1858 1857 2016-06-11T00:59:08Z Rnietzsche 12483 wikitext text/x-wiki ==  Objective of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' ===Encounters=== :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - Pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object and 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. ===Farm=== :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X= Loses coins, 1= Recovers coins, 2/3/3/4= Gains double that many coins). ===Hot Springs=== :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4 points (counts for ''Bather'' accomplishment). ===Panorama=== :('''B''') There are three Panorama types and are made of 3 (Field), 4 (Mountain), or 5 (Paddy) sections. : When a player stops on a Panorama they take the first Panorama of that type that they do not have (value from 1-5) and scores that many points. Each traveler can create only a single panorama of each type and when completed can no longer stop on the spaces corresponding to that type. :('''E''') A player may instead take a Cherry Tree and gain 2 points and 1 coin. (''There are 6 Cherry Tree cards.'') ===Temple=== :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn points. ===Village=== :('''B''') The player draws 3 Souvenir cards and can purchase 1-3 of these cards for 1-3 coins. There are four different Souvenirs and are grouped in sets. The first Souvenir in each set is worth 1 point, the next is 3 points, then 5 and 7 points. :('''E''') Acquire a Legendary Object (counts for ''Collector'' accomplishment) for 1-3 coins: :* Shodo & Emaki - For 1 coin, gain 1 point for each Souvenir or Legendary Object. Gain 1 point for each Souvenir thereafter. :* Buppatsu & Ema - For 2 coins this counts as a different Souvenir type, 5 types in a set is worth 9 points. :* Murasame & Masamune - For 3 coins, gain 8 points. ===Inns=== : All Travelers must stop at each Inn, they may not leave until all players have arrived at that Inn. : The Inns allow players to buy one unique Meal card for 1-3 coins that are worth 6 points. : When the first traveler arrives at an Inn, they draw as many Meal cards as there are players, plus 1. : As players arrive at the Inn they may buy a Meal card to add to their collection, hidden from other players. :* ''A traveler cannot taste the same culinary specialty twice during their journey.'' :* ''A traveler can never purchase more than one Meal card per Inn.'' :* ''A traveler is never obliged to purchase a Meal card.'' == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. == Description of the Travelers == '' '''Name''' (starting coins) Special powers'' === Base Game=== * '''Chuubei''' (4) At intermediate inns, draws encounter card * '''Kinko''' (7) At all inns, buys meals at 1 coin discount * '''Hiroshige''' (3) At intermediate inns, acquires panorama card of choice * '''Hirotada''' (8) At temples, may take 1 coin from the bank and donate it to the temple, scoring 1 point; does this in addition to normal temple action * ''''Mitsukuni''' (6) Earns 1 additional point per hot spring and achievement card * '''Sasayakko''' (5) At villages, when purchasing at least two souvenirs, the cheapest is free; must have enough coins to pay for both at full price * '''Satsuki''' (2) At inns, selects one meal card at random from the set of meal cards; may take it for free or purchase another at full price * '''Umegae''' (5) At encounters, gains 1 coin and 1 point before drawing encounter card * '''Yoshiyasu''' (9) At encounters, draws two encounter cards and keeps one; places other on bottom of deck * '''Zen-emon''' (6) At villages, may purchase one souvenir for 1 coin instead of full price ===Crossroads=== == Game Options == === Initiation === A simplified version with no Travelers and everyone starting with 7 coins. === Return Trip === Instead of starting on the left side of the board, players move right to left. === Gastronomy === The first person arriving at an Inn draws one less card, only drawing one card per player. === Preparations === When leaving the starting Inn, the last player gains two coins, the next gains one coin, the fourth and fifth players each lose a coin. === Crossroads === This expansion adds a second option at each location (other than the Inns) to choose from when stopping. === New Encounters === This adds 4 new encounters to the possibilities when on the 'Encounters' space. f09c51d903da4907081c0ac594efc1f40a4b6341 1859 1858 2016-06-11T00:59:45Z Rnietzsche 12483 /* Base Game */ wikitext text/x-wiki ==  Objective of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' ===Encounters=== :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - Pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object and 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. ===Farm=== :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X= Loses coins, 1= Recovers coins, 2/3/3/4= Gains double that many coins). ===Hot Springs=== :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4 points (counts for ''Bather'' accomplishment). ===Panorama=== :('''B''') There are three Panorama types and are made of 3 (Field), 4 (Mountain), or 5 (Paddy) sections. : When a player stops on a Panorama they take the first Panorama of that type that they do not have (value from 1-5) and scores that many points. Each traveler can create only a single panorama of each type and when completed can no longer stop on the spaces corresponding to that type. :('''E''') A player may instead take a Cherry Tree and gain 2 points and 1 coin. (''There are 6 Cherry Tree cards.'') ===Temple=== :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn points. ===Village=== :('''B''') The player draws 3 Souvenir cards and can purchase 1-3 of these cards for 1-3 coins. There are four different Souvenirs and are grouped in sets. The first Souvenir in each set is worth 1 point, the next is 3 points, then 5 and 7 points. :('''E''') Acquire a Legendary Object (counts for ''Collector'' accomplishment) for 1-3 coins: :* Shodo & Emaki - For 1 coin, gain 1 point for each Souvenir or Legendary Object. Gain 1 point for each Souvenir thereafter. :* Buppatsu & Ema - For 2 coins this counts as a different Souvenir type, 5 types in a set is worth 9 points. :* Murasame & Masamune - For 3 coins, gain 8 points. ===Inns=== : All Travelers must stop at each Inn, they may not leave until all players have arrived at that Inn. : The Inns allow players to buy one unique Meal card for 1-3 coins that are worth 6 points. : When the first traveler arrives at an Inn, they draw as many Meal cards as there are players, plus 1. : As players arrive at the Inn they may buy a Meal card to add to their collection, hidden from other players. :* ''A traveler cannot taste the same culinary specialty twice during their journey.'' :* ''A traveler can never purchase more than one Meal card per Inn.'' :* ''A traveler is never obliged to purchase a Meal card.'' == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. == Description of the Travelers == '' '''Name''' (starting coins) Special powers'' === Base Game=== * '''Chuubei''' (4) At intermediate inns, draws encounter card * '''Kinko''' (7) At inns, buys meals at 1 coin discount * '''Hiroshige''' (3) At intermediate inns, acquires panorama card of choice * '''Hirotada''' (8) At temples, may take 1 coin from the bank and donate it to the temple, scoring 1 point; does this in addition to normal temple action * ''''Mitsukuni''' (6) Earns 1 additional point per hot spring and achievement card * '''Sasayakko''' (5) At villages, when purchasing at least two souvenirs, the cheapest is free; must have enough coins to pay for both at full price * '''Satsuki''' (2) At inns, selects one meal card at random from the set of meal cards; may take it for free or purchase another at full price * '''Umegae''' (5) At encounters, gains 1 coin and 1 point before drawing encounter card * '''Yoshiyasu''' (9) At encounters, draws two encounter cards and keeps one; places other on bottom of deck * '''Zen-emon''' (6) At villages, may purchase one souvenir for 1 coin instead of full price ===Crossroads=== == Game Options == === Initiation === A simplified version with no Travelers and everyone starting with 7 coins. === Return Trip === Instead of starting on the left side of the board, players move right to left. === Gastronomy === The first person arriving at an Inn draws one less card, only drawing one card per player. === Preparations === When leaving the starting Inn, the last player gains two coins, the next gains one coin, the fourth and fifth players each lose a coin. === Crossroads === This expansion adds a second option at each location (other than the Inns) to choose from when stopping. === New Encounters === This adds 4 new encounters to the possibilities when on the 'Encounters' space. 871aed070fcb1ca31d8c5ce52427a929765af10b 1860 1859 2016-06-11T01:02:28Z Rnietzsche 12483 /* Crossroads */ wikitext text/x-wiki ==  Objective of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' ===Encounters=== :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - Pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object and 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. ===Farm=== :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X= Loses coins, 1= Recovers coins, 2/3/3/4= Gains double that many coins). ===Hot Springs=== :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4 points (counts for ''Bather'' accomplishment). ===Panorama=== :('''B''') There are three Panorama types and are made of 3 (Field), 4 (Mountain), or 5 (Paddy) sections. : When a player stops on a Panorama they take the first Panorama of that type that they do not have (value from 1-5) and scores that many points. Each traveler can create only a single panorama of each type and when completed can no longer stop on the spaces corresponding to that type. :('''E''') A player may instead take a Cherry Tree and gain 2 points and 1 coin. (''There are 6 Cherry Tree cards.'') ===Temple=== :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn points. ===Village=== :('''B''') The player draws 3 Souvenir cards and can purchase 1-3 of these cards for 1-3 coins. There are four different Souvenirs and are grouped in sets. The first Souvenir in each set is worth 1 point, the next is 3 points, then 5 and 7 points. :('''E''') Acquire a Legendary Object (counts for ''Collector'' accomplishment) for 1-3 coins: :* Shodo & Emaki - For 1 coin, gain 1 point for each Souvenir or Legendary Object. Gain 1 point for each Souvenir thereafter. :* Buppatsu & Ema - For 2 coins this counts as a different Souvenir type, 5 types in a set is worth 9 points. :* Murasame & Masamune - For 3 coins, gain 8 points. ===Inns=== : All Travelers must stop at each Inn, they may not leave until all players have arrived at that Inn. : The Inns allow players to buy one unique Meal card for 1-3 coins that are worth 6 points. : When the first traveler arrives at an Inn, they draw as many Meal cards as there are players, plus 1. : As players arrive at the Inn they may buy a Meal card to add to their collection, hidden from other players. :* ''A traveler cannot taste the same culinary specialty twice during their journey.'' :* ''A traveler can never purchase more than one Meal card per Inn.'' :* ''A traveler is never obliged to purchase a Meal card.'' == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. == Description of the Travelers == '' '''Name''' (starting coins) Special powers'' === Base Game=== * '''Chuubei''' (4) At intermediate inns, draws encounter card * '''Kinko''' (7) At inns, buys meals at 1 coin discount * '''Hiroshige''' (3) At intermediate inns, acquires panorama card of choice * '''Hirotada''' (8) At temples, may take 1 coin from the bank and donate it to the temple, scoring 1 point; does this in addition to normal temple action * ''''Mitsukuni''' (6) Earns 1 additional point per hot spring and achievement card * '''Sasayakko''' (5) At villages, when purchasing at least two souvenirs, the cheapest is free; must have enough coins to pay for both at full price * '''Satsuki''' (2) At inns, selects one meal card at random from the set of meal cards; may take it for free or purchase another at full price * '''Umegae''' (5) At encounters, gains 1 coin and 1 point before drawing encounter card * '''Yoshiyasu''' (9) At encounters, draws two encounter cards and keeps one; places other on bottom of deck * '''Zen-emon''' (6) At villages, may purchase one souvenir for 1 coin instead of full price ===Crossroads=== * '''Daigoro''' (3) At inns, draws souvenir card == Game Options == === Initiation === A simplified version with no Travelers and everyone starting with 7 coins. === Return Trip === Instead of starting on the left side of the board, players move right to left. === Gastronomy === The first person arriving at an Inn draws one less card, only drawing one card per player. === Preparations === When leaving the starting Inn, the last player gains two coins, the next gains one coin, the fourth and fifth players each lose a coin. === Crossroads === This expansion adds a second option at each location (other than the Inns) to choose from when stopping. === New Encounters === This adds 4 new encounters to the possibilities when on the 'Encounters' space. 6bd1777d00115c1dac180f8a04b76b9dd4dfa027 1861 1860 2016-06-11T01:18:55Z Rnietzsche 12483 /* Description of the Travelers */ wikitext text/x-wiki ==  Objective of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' ===Encounters=== :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - Pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object and 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. ===Farm=== :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X= Loses coins, 1= Recovers coins, 2/3/3/4= Gains double that many coins). ===Hot Springs=== :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4 points (counts for ''Bather'' accomplishment). ===Panorama=== :('''B''') There are three Panorama types and are made of 3 (Field), 4 (Mountain), or 5 (Paddy) sections. : When a player stops on a Panorama they take the first Panorama of that type that they do not have (value from 1-5) and scores that many points. Each traveler can create only a single panorama of each type and when completed can no longer stop on the spaces corresponding to that type. :('''E''') A player may instead take a Cherry Tree and gain 2 points and 1 coin. (''There are 6 Cherry Tree cards.'') ===Temple=== :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn points. ===Village=== :('''B''') The player draws 3 Souvenir cards and can purchase 1-3 of these cards for 1-3 coins. There are four different Souvenirs and are grouped in sets. The first Souvenir in each set is worth 1 point, the next is 3 points, then 5 and 7 points. :('''E''') Acquire a Legendary Object (counts for ''Collector'' accomplishment) for 1-3 coins: :* Shodo & Emaki - For 1 coin, gain 1 point for each Souvenir or Legendary Object. Gain 1 point for each Souvenir thereafter. :* Buppatsu & Ema - For 2 coins this counts as a different Souvenir type, 5 types in a set is worth 9 points. :* Murasame & Masamune - For 3 coins, gain 8 points. ===Inns=== : All Travelers must stop at each Inn, they may not leave until all players have arrived at that Inn. : The Inns allow players to buy one unique Meal card for 1-3 coins that are worth 6 points. : When the first traveler arrives at an Inn, they draw as many Meal cards as there are players, plus 1. : As players arrive at the Inn they may buy a Meal card to add to their collection, hidden from other players. :* ''A traveler cannot taste the same culinary specialty twice during their journey.'' :* ''A traveler can never purchase more than one Meal card per Inn.'' :* ''A traveler is never obliged to purchase a Meal card.'' == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. == Description of the Travelers == '' '''Name''' (starting coins) Special powers'' === Base Game=== * '''Chuubei''' (4) At intermediate inns, before meal, draws encounter card * '''Kinko''' (7) At inns, buys meals at 1 coin discount * '''Hiroshige''' (3) At intermediate inns, before meal, acquires panorama card of choice * '''Hirotada''' (8) At temple spaces, may take 1 coin from the bank and donate it to the temple, scoring 1 point; does this in addition to normal temple action * ''''Mitsukuni''' (6) Earns 1 additional point per hot spring and achievement card * '''Sasayakko''' (5) At village spaces, when purchasing at least two souvenirs, the cheapest is free; must have enough coins to pay for both at full price * '''Satsuki''' (2) At inns, selects one meal card at random from the set of meal cards; may take it for free or purchase another at full price * '''Umegae''' (5) At encounter spaces, gains 1 coin and 1 point before drawing encounter card * '''Yoshiyasu''' (9) At encounter spaces, draws two encounter cards and keeps one; places other on bottom of deck * '''Zen-emon''' (6) At village spaces, may purchase one souvenir for 1 coin instead of full price ===Crossroads=== * '''Daigoro''' (3) At intermediate inns, before meal, draws souvenir card * '''Gotozaemon''' (0) At panorama spaces, gains 1 additional coin * '''Jirocho''' (5) At intermediate inns, before meal, may gamble 1 coin; player throws the fortune die and follows normal rules for gambling * '''Kita''' (4) At encounter spaces, may take both actions (draw encounter card '''and''' buy calligraphy card) * '''Miyataka''' (4) At temple spaces, may take both actions (donate coins '''and''' buy amulet) * '''Nampo''' (2) At inns, earns 1 point per coin value of meal eaten == Game Options == === Initiation === A simplified version with no Travelers and everyone starting with 7 coins. === Return Trip === Instead of starting on the left side of the board, players move right to left. === Gastronomy === The first person arriving at an Inn draws one less card, only drawing one card per player. === Preparations === When leaving the starting Inn, the last player gains two coins, the next gains one coin, the fourth and fifth players each lose a coin. === Crossroads === This expansion adds a second option at each location (other than the Inns) to choose from when stopping. === New Encounters === This adds 4 new encounters to the possibilities when on the 'Encounters' space. 1abae0a3f9ba738a7d9d2bf64fad448212513988 Your game state machine: states.inc.php 0 90 1862 1661 2016-06-15T14:04:07Z Victoria la 11989 /* action */ wikitext text/x-wiki This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). Important: to understand the game state machine, the best is to read this presentation first: [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] == Overall structure == The machine states is described by a PHP associative array. Example: <pre> $machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ), </pre> == Syntax == === id === The keys determine game states IDs (in the example above: 1 and 2). IDs must be positive integers. ID=1 is reserved for the first game state and should not be used (and you must not modify it). ID=99 is reserved for the last game state of the game (end of the game) (and you must not modify it). Note: you may use any ID, even ID greater than 100. But you cannot use 1 and 99. Note²: You can't of course use the same ID twice. Note³: When a game is in prod and you change the ID of a state, all active games (including many turn based) will behave unpredictably. === name === (mandatory) The name of a game state is used to identify it in your game logic. Several game states can share the same name, however this is not recommended. Warning! Not put spaces in the name. This could cause problems in some cases unexpected. PHP example: <pre> // Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... } </pre> JS example: <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break; </pre> === type === (mandatory) You can use 3 types of game states: * activeplayer (1 player is active and must play) * multipleactiveplayer (1..N players can be active and must play) * game (no player is active. This is a transitional state to do something automatic specified by game rules) === description === (mandatory) The description is the string that is displayed in the main action bar (top of the screen) when the state is active. When a string is specified as a description, you must use "clienttranslate" in order the string can be translate on the client side: <pre> "description" => clienttranslate('${actplayer} must play a card or pass'), </pre> In the description string, you can use ${actplayer} to refer to the active player. You can also use custom arguments in your description. These custom arguments correspond to values returned by your "args" PHP method (see below "args" field). Example of custom field: <pre> In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "args" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); } </pre> Note: You may specify an empty string ("") here if it never happens that the game remains in this state (ie: if this state immediately jump to another state when activated). Note²: Usually, you specify a string for "activeplayer" and "multipleactiveplayer" game states, and you specify an empty string for "game" game states. BUT, if you are using synchronous notifications, the client can remains few seconds on a "game" type game state, and in this case this may be useful to display a description in the status bar during this state. === descriptionmyturn === (mandatory for "activeplayer" and "multipleactiveplayer" game states type) "descriptionmyturn" has exactly the same role and properties than "description", except that this value is displayed to the current active player - or to all active players in case of a multipleactiveplayer game state. In general, we have this situation: <pre> "description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'), </pre> Note: you can use ${you} in description my turn in order the description can display "You" instead of the name of the player. === action === (mandatory for "game" game state type) "action" specify a PHP method to call when entering into this game state. Example: <pre> In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state </pre> Usually, for "game" game state type, the action method is used to do some automatic stuff specified by the rules (ex: check victory conditions, deal cards for a new round, go to the next player...) and then jump to another game state. Note: a BGA convention specify that PHP method called with "action" are prefixed by "st". Note: this field CAN be used for player states to set something up, i.e. for multi player states it can make all players active === transitions === (mandatory) With "transition" you specify in which game state you can jump from a given game state. Example: <pre> 25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... } </pre> In the example above, if "myGameState" is the current active game state, I can jump to game state with ID 27, or game state with ID 39. Example to jump to ID 27: <pre> In mygame.game.php: $this->gamestate->nextState( "nextPlayer" ); </pre> Important: "nextPlayer" is the name of the transition, and NOT the name of the target game state. Several transitions can lead to the same game state. Note: if you have only 1 transition, you may give it an empty name. Example: <pre> In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here </pre> === possibleactions === (mandatory for "activeplayer" and "multipleactiveplayer" game states) "possibleactions" defines the actions possible by the players at this game state. By defining "possibleactions", you make sure players can't do actions that they are not allowed to do at this game states. Example: <pre> In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will failed if "playCard" is not specified in "possibleactions" in current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will failed if "playCard" is not specified in "possibleactions" in current game state. { return ; } .... </pre> === args === (optional) From time to time, it happens that you need some information on the client side (ie : for your game interface) only for a specific game state. Example 1 : for Reversi, the list of possible moves during playerTurn state. Example 2 : in Caylus, the number of remaining king's favor to choose in the state where the player is choosing a favor. Example 3 : in Can't stop, the list of possible die combination to be displayed to the active player in order he can choose among them. In such a situation, you can specify a method name as the « args » argument for your game state. This method must get some piece of information about the game (ex : for Reversi, the possible moves) and return them. Thus, this data can be transmitted to the clients and used by the clients to display it. It should always be an associative array. Let's see a complete example using args with « Reversi » game : In states.inc.php, we specify some « args » argument for gamestate « playerTurn » : <pre> 10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", <================================== HERE "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ), </pre> It corresponds to a « argPlayerTurn » method in our PHP code (reversi.game.php): <pre> function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves() ); } </pre> Then, when we enter into « playerTurn » game state on the client side, we can highlight the possible moves on the board using information returned by argPlayerTurn : <pre> onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } }, </pre> Note: you can also use values returned by your "args" method to have some custom values in your "description"/"descriptionmyturn" (see above). Note: as a BGA convention, PHP methods called with "args" are prefixed by "arg" (ex: argPlayerTurn). Warning: the "args" method can be called before the "action" method so don't expect data modifications by the "action" method to be available in the "args" method! ==== Private infos in args ==== By default, all data provided through this method are PUBLIC TO ALL PLAYERS. Please do not send any private data with this method, as a cheater could see it even it is not used explicitly by the game interface logic. This is although possible to specify that some data should be sent to some specific players only: Example 1: send an information to active player(s) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private 'active' => array( // Using "active" keyword inside "_private", you select active player(s) 'somePrivateData' => self::getSomePrivateData() // will be send only to active player(s) ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> Inside the js file, these variables will be available through `args._private`. (e.g. `args._private.somePrivateData` -- it is not `args._private.active.somePrivateData` nor is it `args.somePrivateData`) Example 2: send an information to a specific player (<specific_player_id>) only: <pre> function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private <specific_player_id> => array( // you select one specific player with its id 'somePrivateData' => self::getSomePrivateData() // will be send only to <specific_player_id> ) ), 'possibleMoves' => self::getPossibleMoves() // will be send to all players ); } </pre> IMPORTANT: in certain situation (ex: multipleactiveplayer game state) these "private data" features can have a big performance impact. Please do not use if not needed. === updateGameProgression === (optional) IF you specify "updateGameProgression => true" in a game state, your "getGameProgression" PHP method will be called at the beginning of this game state - and thus the game progression of the game will be updated. At least one of your game state (any of them) must specify updateGameProgression=>true. 29435f65c2c4798bc6547b46ddb2573952060c92 Game options and preferences: gameoptions.inc.php 0 219 1865 2016-06-18T19:59:59Z Victoria la 11989 Created page with "In this file, you can define your game options (= game variants). Note: If your game has no variant, you don't have to modify this file. // note: game variant ID sho..." wikitext text/x-wiki In this file, you can define your game options (= game variants). Note: If your game has no variant, you don't have to modify this file. // note: game variant ID should start at 100 (ie: 100, 101, 102, ...). The maximum is 199. 100 => array( 'name' => totranslate('my game option'), 'values' => array( // A simple value for this option: 1 => array( 'name' => totranslate('option 1') ) // A simple value for this option. // If this value is chosen, the value of "tmdisplay" is displayed in the game lobby 2 => array( 'name' => totranslate('option 2'), 'tmdisplay' => totranslate('option 2') ), // Another value, with other options: // beta=true => this option is in beta version right now. // nobeginner=true => this option is not recommended for beginners 3 => array( 'name' => totranslate('option 3'), 'beta' => true, 'nobeginner' => true ),) ) ) ) Note²: All options defined in this file should have a corresponding "game state labels" with the same ID (see "initGameStateLabels" in yourgame.game.php) self::initGameStateLabels ( array ( ... "my_first_game_variant" => 100, ) ); 13ef4277f7fdb8c76309224e2923fe574c7652f2 1874 1865 2016-06-21T00:18:10Z Victoria la 11989 wikitext text/x-wiki In this file, you can define your game options (= game variants). Note: If your game has no variant, you don't have to modify this file. <pre> $game_options = array ( 100 => array ( 'name' => totranslate ( 'my game option' ), 'values' => array ( // A simple value for this option: 1 => array ( 'name' => totranslate ( 'option 1' ) ), // A simple value for this option. // If this value is chosen, the value of "tmdisplay" is displayed in the game lobby 2 => array ( 'name' => totranslate ( 'option 2' ), 'tmdisplay' => totranslate ( 'option 2' ) ), // Another value, with other options: // beta=true => this option is in beta version right now. // nobeginner=true => this option is not recommended for beginners 3 => array ( 'name' => totranslate ( 'option 3' ), 'beta' => true, 'nobeginner' => true ) ) ) ); </pre> Note²: All options defined in this file should have a corresponding "game state labels" with the same ID (see "initGameStateLabels" in yourgame.game.php) self::initGameStateLabels ( array ( ... "my_first_game_variant" => 100, ) ); 3a9c0a7f77a3caadb0560fbc2704acd59c71a476 1875 1874 2016-06-21T02:03:22Z Victoria la 11989 wikitext text/x-wiki In this file, you can define your game options (= game variants). Note: If your game has no variant, you don't have to modify this file. <pre> $game_options = array ( 100 => array ( 'name' => totranslate ( 'my game option' ), 'values' => array ( // A simple value for this option: 1 => array ( 'name' => totranslate ( 'option 1' ) ), // A simple value for this option. // If this value is chosen, the value of "tmdisplay" is displayed in the game lobby 2 => array ( 'name' => totranslate ( 'option 2' ), 'tmdisplay' => totranslate ( 'option 2' ) ), // Another value, with other options: // beta=true => this option is in beta version right now. // nobeginner=true => this option is not recommended for beginners 3 => array ( 'name' => totranslate ( 'option 3' ), 'beta' => true, 'nobeginner' => true ) ) ) ); </pre> Note²: All options defined in this file should have a corresponding "game state labels" with the same ID (see "initGameStateLabels" in yourgame.game.php) self::initGameStateLabels ( array ( ... "my_first_game_variant" => 100, ) ); IMPORTANT: After you edited and deployed this file you have to go to control panel and press "Reload game options configuration" 2adbc5bd1eac365825f71e514f03ac436e9e721d Studio 0 49 1866 1709 2016-06-18T20:24:23Z Victoria la 11989 /* BGA Studio user guide */ wikitext text/x-wiki [[File:Bga_studio_small.jpg]] Note: Please DO NOT translate Studio Documentation, so that there can be one place where you can find the latest information available. == What is Board Game Arena Studio? == '''Board Game Arena Studio''' is a platform to build online board game adaptation using the Board Game Arena platform. It is open to any gamer with development skills :) BGA Studio website: http://en.studio.boardgamearena.com (original announcement on BGA forum: http://forum.boardgamearena.com/viewtopic.php?f=10&t=1973) == Discover BGA Studio in 5 presentations == Why, how, what... to start discovering BGA Studio, we prepared 5 "powerpoint" presentations for you: * [http://www.slideshare.net/boardgamearena/5-reasons-why-you-should-use-bga-studio-for-your-online-board-game 5 reasons why you should use BGA Studio for your online board game] * [http://www.slideshare.net/boardgamearena/the-8-steps-to-create-a-board-game-on-board-game-arena The 8 steps to create a board game on Board Game Arena] * [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] * [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine Focus on BGA game state machine] * [http://www.slideshare.net/boardgamearena/bga-studio-guidelines BGA developers guidelines] == How to join the BGA developer team? == Please see this page: [[How to join BGA developer team?]] == Great, I'm in! ... How should I start? == If you didn't already, check the presentations at the top of this page to get the basics. Then, you should checkout the [[First steps with BGA Studio]] to make sure that runs fine. After that, we advise you to take a peek at one or both of these two game creation tutorials: * [[Tutorial reversi]] * [[Tutorial gomoku]] Then start editing files and see what happens! ;) If you have any questions, please check out the '''[[Studio FAQ]]''' first, then if you didn't find the answer you were looking for, please post your question on the [http://forum.boardgamearena.com/viewforum.php?f=12 '''development forum''']. == BGA Studio documentation == === BGA Studio Framework reference === This part of the documentation focuses on the development framework itself: functions and methods available to build your game. [[Studio file reference|File structure of a BGA game]] ==== Game logic ==== * [[Main game logic: yourgamename.game.php]] * [[Your game state machine: states.inc.php]] * [[Game database model: dbmodel.sql]] * [[Players actions: yourgamename.action.php]] * [[Game material description: material.inc.php]] * [[Game statistics: stats.inc.php]] ==== Game interface ==== * [[Game interface logic: yourgamename.js]] * [[Game art: img directory]] * [[Game interface stylesheet: yourgamename.css]] * [[Game layout: view and template: yourgamename.view.php and yourgamename_yourgamename.tpl]] * [[Your game mobile version]] ==== Other components ==== * [[Translations]] (how to make your game translatable) * [[Game options and preferences: gameoptions.inc.php]] * [[Game meta-information: gameinfos.inc.php]] * [[Game replay]] === BGA Studio game components reference === Game components are useful tools you can use in your game adaptations. * [[Deck]]: a PHP component to manage cards (deck, hands, picking cards, moving cards, shuffle deck, ...). * [[Counter]]: a JS component to manage a counter that can increase/decrease (ex: player's score). * [[Draggable]]: a JS component to manage drag'n'drop actions. * [[ExpandableSection]]: a JS component to manage a rectangular block of HTML than can be displayed/hidden. * [[Scrollmap]]: a JS component to manage a scrollable game area (useful when the game area can be infinite. Examples: Saboteur or Takenoko games). * [[Stock]]: a JS component to manage and display a set of game elements displayed at a position. * [[Wrapper]]: a JS component to wrap a &lt;div&gt; element around his child, even if these elements are absolute positioned. * [[Zone]]: a JS component to manage a zone of the board where several game elements can come and leave, but should be well displayed together (See for example: token's places at Can't Stop). === BGA Studio user guide === This part of the documentation is a user guide for the BGA Studio online development environment. * [[Tools and tips of BGA Studio]] * [[Practical debugging]] * [[Studio logs]] * [[Studio FAQ]] * [[Troubleshooting]] == BGA Developer team organization == * [[Steps to create a BGA game]] * [[Post-release phase]] == Other resources == [http://forum.boardgamearena.com/viewforum.php?f=12 Development forum] [http://forum.boardgamearena.com/viewforum.php?f=4 Bugs forum] b92effda0e1a5447b55c613feddfc2abb88cfd43 Troubleshooting 0 220 1867 2016-06-18T20:30:21Z Victoria la 11989 Created page with "Describing common errors which is hard to understand and debug == Game does not start at all == === Undefined offset: 0 in table/table.game.php on line 830 === You are lik..." wikitext text/x-wiki Describing common errors which is hard to understand and debug == Game does not start at all == === Undefined offset: 0 in table/table.game.php on line 830 === You are likely calling self::getActivePlayerName () during setupNewGame() 28dfa7031995a7ea5df4783a9d2af35e6efaa53d 1868 1867 2016-06-18T20:51:55Z Victoria la 11989 /* Game does not start at all */ wikitext text/x-wiki Describing common errors which is hard to understand and debug == Game does not start at all == === Undefined offset: 0 in table/table.game.php on line 830 === You are likely calling self::getActivePlayerName () during setupNewGame() === Unexpected error: Wrong formatted data from BGA gameserver 1 (method: createGame): ... === This is generic message usually followed by exact position in your source code, and usually its syntax error in one of yours php script == Predefined server errors == === Unexpected final state XX === The action function does not transition to any state, i.e. selectField($field) { self::checkAction ( 'selectField' ); if ($field!=0) $this->gamestate->nextState ( 'next' ); } Here if $field is 0 there is no transition == Game interface hangs during reload == Showing "Application Loading..." === Javascript error: During pageload undefined no_stack_avail Script: === This error usually has no useful data, but it means you called somes API that require a callback and did not define callback function, i.e in dojo.connect, this.connectClass, dojo.subscribe, etc this.connectClass('field', 'onclick', 'onField'); // <-- onField is not defined 64fd5ea8496d1e49c40346fd89ecbfb3818fee5a 1869 1868 2016-06-18T21:35:22Z Victoria la 11989 /* Predefined server errors */ wikitext text/x-wiki Describing common errors which is hard to understand and debug == Game does not start at all == === Undefined offset: 0 in table/table.game.php on line 830 === You are likely calling self::getActivePlayerName () during setupNewGame() === Unexpected error: Wrong formatted data from BGA gameserver 1 (method: createGame): ... === This is generic message usually followed by exact position in your source code, and usually its syntax error in one of yours php script == Predefined server errors == === Unexpected final state XX === The action function does not transition to any state, i.e. selectField($field) { self::checkAction ( 'selectField' ); if ($field!=0) $this->gamestate->nextState ( 'next' ); } Here if $field is 0 there is no transition === This game action is impossible right now === Check the game log. Usually your state does not define the action you trying to perform in 'possibeactions' array. === Unexpected error: This transition (playerTurn) is impossible at this state (42) This is pretty self explanatory. Function nextState() takes transition name not a state name, so you probably did not define this transition that the given state == Game interface hangs during reload == Showing "Application Loading..." === Javascript error: During pageload undefined no_stack_avail Script: === This error usually has no useful data, but it means you called somes API that require a callback and did not define callback function, i.e in dojo.connect, this.connectClass, dojo.subscribe, etc this.connectClass('field', 'onclick', 'onField'); // <-- onField is not defined d472fa7f714c9687c56d5571af6fa4cb4c32cf23 1870 1869 2016-06-18T21:35:32Z Victoria la 11989 /* This game action is impossible right now */ wikitext text/x-wiki Describing common errors which is hard to understand and debug == Game does not start at all == === Undefined offset: 0 in table/table.game.php on line 830 === You are likely calling self::getActivePlayerName () during setupNewGame() === Unexpected error: Wrong formatted data from BGA gameserver 1 (method: createGame): ... === This is generic message usually followed by exact position in your source code, and usually its syntax error in one of yours php script == Predefined server errors == === Unexpected final state XX === The action function does not transition to any state, i.e. selectField($field) { self::checkAction ( 'selectField' ); if ($field!=0) $this->gamestate->nextState ( 'next' ); } Here if $field is 0 there is no transition === This game action is impossible right now === Check the game log. Usually your state does not define the action you trying to perform in 'possibeactions' array. === Unexpected error: This transition (playerTurn) is impossible at this state (42) === This is pretty self explanatory. Function nextState() takes transition name not a state name, so you probably did not define this transition that the given state == Game interface hangs during reload == Showing "Application Loading..." === Javascript error: During pageload undefined no_stack_avail Script: === This error usually has no useful data, but it means you called somes API that require a callback and did not define callback function, i.e in dojo.connect, this.connectClass, dojo.subscribe, etc this.connectClass('field', 'onclick', 'onField'); // <-- onField is not defined 7d86cf6636bcb791c49a4346bd7fff5457cab183 1871 1870 2016-06-18T23:18:14Z Victoria la 11989 /* Game does not start at all */ wikitext text/x-wiki Describing common errors which is hard to understand and debug == Game does not start at all == === Undefined offset: 0 in table/table.game.php on line 830 === You are likely calling self::getActivePlayerName () during setupNewGame() === Unexpected error: Wrong formatted data from BGA gameserver 1 (method: createGame): ... === This is generic message usually followed by exact position in your source code, and usually its syntax error in one of yours php script === Unexpected error: Propagating error from GS 1 (method: createGame): Fatal error during yourgame setup: Not logged === Calling self::getCurrentPlayerId () from arg* state method (in first state of the game) == Predefined server errors == === Unexpected final state XX === The action function does not transition to any state, i.e. selectField($field) { self::checkAction ( 'selectField' ); if ($field!=0) $this->gamestate->nextState ( 'next' ); } Here if $field is 0 there is no transition === This game action is impossible right now === Check the game log. Usually your state does not define the action you trying to perform in 'possibeactions' array. === Unexpected error: This transition (playerTurn) is impossible at this state (42) === This is pretty self explanatory. Function nextState() takes transition name not a state name, so you probably did not define this transition that the given state == Game interface hangs during reload == Showing "Application Loading..." === Javascript error: During pageload undefined no_stack_avail Script: === This error usually has no useful data, but it means you called somes API that require a callback and did not define callback function, i.e in dojo.connect, this.connectClass, dojo.subscribe, etc this.connectClass('field', 'onclick', 'onField'); // <-- onField is not defined e4ed21f3c448ae6f69a473ea45c7f6613412ab3a 1872 1871 2016-06-18T23:57:38Z Victoria la 11989 wikitext text/x-wiki Describing common errors which is hard to understand and debug == Game does not start at all == === Undefined offset: 0 in table/table.game.php on line 830 === You are likely calling self::getActivePlayerName () during setupNewGame() === Unexpected error: Wrong formatted data from BGA gameserver 1 (method: createGame): ... === This is generic message usually followed by exact position in your source code, and usually its syntax error in one of yours php script === Unexpected error: Propagating error from GS 1 (method: createGame): Fatal error during yourgame setup: Not logged === Calling self::getCurrentPlayerId () from arg* state method (in first state of the game) == Predefined server errors == === Unexpected error: Unexpected final game state (XX) === The action function does not transition to any state, i.e. selectField($field) { self::checkAction ( 'selectField' ); if ($field!=0) $this->gamestate->nextState ( 'next' ); } Here if $field is 0 there is no transition === This game action is impossible right now === Check the game log. Usually your state does not define the action you trying to perform in 'possibeactions' array. === Unexpected error: This transition (playerTurn) is impossible at this state (42) === This is pretty self explanatory. Function nextState() takes transition name not a state name, so you probably did not define this transition that the given state == Game interface hangs during reload == Showing "Application Loading..." === Javascript error: During pageload undefined no_stack_avail Script: === This error usually has no useful data, but it means you called somes API that require a callback and did not define callback function, i.e in dojo.connect, this.connectClass, dojo.subscribe, etc this.connectClass('field', 'onclick', 'onField'); // <-- onField is not defined 5da8d61079598a406d6a3204ddd594630b6685a1 1878 1872 2016-06-23T03:08:05Z Victoria la 11989 wikitext text/x-wiki Describing common errors which is hard to understand and debug == Game does not start at all == === Undefined offset: 0 in table/table.game.php on line 830 === You are likely calling self::getActivePlayerName () during setupNewGame() === Unexpected error: Wrong formatted data from BGA gameserver 1 (method: createGame): ... === This is generic message usually followed by exact position in your source code, and usually its syntax error in one of yours php script === Unexpected error: Propagating error from GS 1 (method: createGame): Fatal error during yourgame setup: Not logged === Calling self::getCurrentPlayerId () from arg* state method (in first state of the game) == Predefined server errors == === Unexpected error: Unexpected final game state (XX) === The action function does not transition to any state, i.e. selectField($field) { self::checkAction ( 'selectField' ); if ($field!=0) $this->gamestate->nextState ( 'next' ); } Here if $field is 0 there is no transition === This game action is impossible right now === Check the game log. Usually your state does not define the action you trying to perform in 'possibeactions' array. === Unexpected error: This transition (playerTurn) is impossible at this state (42) === This is pretty self explanatory. Function nextState() takes transition name not a state name, so you probably did not define this transition that the given state == Game interface hangs during reload == Showing "Application Loading..." === Javascript error: During pageload undefined no_stack_avail Script: === This error usually has no useful data, but it means you called somes API that require a callback and did not define callback function, i.e in dojo.connect, this.connectClass, dojo.subscribe, etc this.connectClass('field', 'onclick', 'onField'); // <-- onField is not defined == Game interface spins in a loop throwing error == Errors is something like "Cannot read property 'is_ai' of undefined". Cannot restart the game because cannot access UI to stop. Likely you get in actplayer state with player id == 0. The only way to fix it is to edit database, globals index == 2 set player id to one of your test dudes (can copy from row % for example). 31ddf4856c9d2145f0357afd5be1a2f2de84822b 1880 1878 2016-06-29T00:20:20Z Victoria la 11989 /* Game interface spins in a loop throwing error */ wikitext text/x-wiki Describing common errors which is hard to understand and debug == Game does not start at all == === Undefined offset: 0 in table/table.game.php on line 830 === You are likely calling self::getActivePlayerName () during setupNewGame() === Unexpected error: Wrong formatted data from BGA gameserver 1 (method: createGame): ... === This is generic message usually followed by exact position in your source code, and usually its syntax error in one of yours php script === Unexpected error: Propagating error from GS 1 (method: createGame): Fatal error during yourgame setup: Not logged === Calling self::getCurrentPlayerId () from arg* state method (in first state of the game) == Predefined server errors == === Unexpected error: Unexpected final game state (XX) === The action function does not transition to any state, i.e. selectField($field) { self::checkAction ( 'selectField' ); if ($field!=0) $this->gamestate->nextState ( 'next' ); } Here if $field is 0 there is no transition === This game action is impossible right now === Check the game log. Usually your state does not define the action you trying to perform in 'possibeactions' array. === Unexpected error: This transition (playerTurn) is impossible at this state (42) === This is pretty self explanatory. Function nextState() takes transition name not a state name, so you probably did not define this transition that the given state == Game interface hangs during reload == Showing "Application Loading..." === Javascript error: During pageload undefined no_stack_avail Script: === This error usually has no useful data, but it means you called somes API that require a callback and did not define callback function, i.e in dojo.connect, this.connectClass, dojo.subscribe, etc this.connectClass('field', 'onclick', 'onField'); // <-- onField is not defined == Game interface spins in a loop throwing error == Errors is something like "Cannot read property 'is_ai' of undefined". Cannot restart the game because cannot access UI to stop. Likely you get in actplayer state with player id == 0. The only way to fix it is to edit database, globals index == 2 set player id to one of your test dudes (can copy from row 5 for example). 20ee97124aaa6e8f37da8435af18fcf3023d32ed 1881 1880 2016-07-07T00:32:01Z Victoria la 11989 /* Game interface hangs during reload */ wikitext text/x-wiki Describing common errors which is hard to understand and debug == Game does not start at all == === Undefined offset: 0 in table/table.game.php on line 830 === You are likely calling self::getActivePlayerName () during setupNewGame() === Unexpected error: Wrong formatted data from BGA gameserver 1 (method: createGame): ... === This is generic message usually followed by exact position in your source code, and usually its syntax error in one of yours php script === Unexpected error: Propagating error from GS 1 (method: createGame): Fatal error during yourgame setup: Not logged === Calling self::getCurrentPlayerId () from arg* state method (in first state of the game) == Predefined server errors == === Unexpected error: Unexpected final game state (XX) === The action function does not transition to any state, i.e. selectField($field) { self::checkAction ( 'selectField' ); if ($field!=0) $this->gamestate->nextState ( 'next' ); } Here if $field is 0 there is no transition === This game action is impossible right now === Check the game log. Usually your state does not define the action you trying to perform in 'possibeactions' array. === Unexpected error: This transition (playerTurn) is impossible at this state (42) === This is pretty self explanatory. Function nextState() takes transition name not a state name, so you probably did not define this transition that the given state == Game interface hangs during reload or on start == Showing "Application Loading..." === Javascript error: During pageload undefined no_stack_avail Script: === This error usually has no useful data, but it means you called somes API that require a callback and did not define callback function, i.e in dojo.connect, this.connectClass, dojo.subscribe, etc this.connectClass('field', 'onclick', 'onField'); // <-- onField is not defined === Unexpected Syntax Error: === No further details in the log. When log is filling with some social connect errors. Possible Reason: Syntax error in of the php script which is loaded before the start, such as gameoptions.inc.php, gameinfos.inc.php and such. == Game interface spins in a loop throwing error == Errors is something like "Cannot read property 'is_ai' of undefined". Cannot restart the game because cannot access UI to stop. Likely you get in actplayer state with player id == 0. The only way to fix it is to edit database, globals index == 2 set player id to one of your test dudes (can copy from row 5 for example). 806d9bbac19cef238f81827ece9a5dc0b8c5ecbb Gamehelpbackgammon 0 213 1876 1780 2016-06-21T19:04:48Z Otithes 13529 wikitext text/x-wiki '''Objective''' Players roll dice to advance their pieces into their home base, after completed, resume by rolling dice to remove their pieces from the board. First player to clear all pieces from the board wins. '''Setup''' The game has a fixed setup, with opponent mirrored arrangement. Each players home row is opposite the other, and each will be moving in only one, opposite direction around the board (either clockwise or counter-clockwise). '''Play''' Each roll of two dice can be played to advance one piece both numbers in sum, or split play as each die to advance one piece respectively. Should any number roll as double, player is able to play that number four times, as board will allow. Pieces cannot be moved to land on any space occupied by two or more opposing pieces. Your own pieces may accumulate in any quantity on your own occupied spaces. '''Capture''' Any piece stacked two or more is safe from capture. Any piece single on a space is vulnerable. Rolling number combination to land your piece on exposed opponent piece is a capture and token must sit out of play until a number roll allows entry into opposing home row (i.e farthest from own). No other piece may be moved until all captured pieces have re-entered the game. ce71d2804e4107ae6e91480b1694ecd93cb0fb3e Gamehelpdragonheart 0 31 1877 1396 2016-06-22T06:32:14Z Nandblock 11082 /* Cards */ wikitext text/x-wiki ==Summary== Dragonheart is a two player card game where the goal is to collect as many points as possible by placing your cards on the board and collecting the cards already placed there. There are 9 different cards, each with their own rules as to which cards can be collected when they are placed down. ==Goal== To have the most points by the end of the game. ==Game Start== At the start of the game, each player takes five cards from their deck and the Great Dragon piece is put on the board. ==End== The game ends when all nine ship cards have been used, or one players deck is exhausted. At that point, each player adds the value of all the cards in their respective piles, plus 3 extra points to whomever has the Great Dragon piece. Whoever has the most points, wins the game. In case of a tie, the player with the Great Dragon wins. ==Turns== Players alternate turns, putting down and picking up cards. A player may choose to put down as many cards of the same type as he or she wants to. The cards get placed on their corresponding picture on the game board. Depending on what was placed, a player may take cards from the board to put in their pile, or move cards to the bottom of the board, below the ship. ==Cards== There are nine types of cards in the game. Cards have a point value to them listed as a number in the corner, that is unrelated to what type of card it is. Arrows on the board indicate what cards can take what. * ''Dwarf'': The player who places the fourth dwarf on the board, takes all four of the dwarf cards. No other card allows a player to take a dwarf. * ''Huntress'': The player who places the third huntress card, takes all fire dragon cards from the board. At that point, the three huntress cards are moved to the bottom of the board. * ''Fire Dragon'': Each time a fire dragon is placed, the player takes all of the treasure chest cards. * ''Treasure Chest'': Placing this card has no action, but it can be taken by a fire dragon or sorceress. * ''Troll'': Placing this card allows the player to take the sorceress pile. * ''Knight'': The player who places the second knight card, may choose to take either the sorceress or troll pile. Afterwards, the two knight cards are placed at the bottom of the board. * ''Petrified Dragon'': Placing this card has no effect, but when it is taken by a sorceress, the Great Dragon piece is taken too, either from the board or from the opponent. * ''Sorceress'': Placing a sorceress allows the player to take either the petrified dragon pile, or the treasure pile. Taking the petrified dragon cards (if there are any on the board) gives the player possession of the Great Dragon. * ''Ship'': The third ship card placed, allows the player to take all the knight and huntress cards placed at the bottom of the table. The ship cards are then discarded. The third time that three ship cards are played ends the game and the opponent takes one final turn. * ''Great Dragon'': The great dragon piece goes to the last player to take a petrified dragon stack. Possession of the Great Dragon gives the player an extra card, plus three extra points at the end of the game. If the dragon is taken from an opponent, then that opponent's hand is reduced to five cards again: a random card is removed from the hand and placed back on top of their deck. '''Card Distribution in each deck''' * ''Dwarf'': 10 - (1,1,1,1,1,1,2,2,2,3) * ''Huntress'': 6 - (1,1,1,1,2,2) * ''Fire Dragon'': 4 - (2,3,3,4) * ''Treasure Chest'': 7 - (1,1,2,2,3,3,4) * ''Troll'': 3 - (1,2,3) * ''Knight'': 5 - (1,1,1,1,2) * ''Petrified Dragon'': 5 (2,2,2,2,2) * ''Sorceress'': 4 - (1,1,2,2) * ''Ship'': 6 7330ca4af7b9a75f2ff4a9061a72c816f0301cdb Game layout: view and template: yourgamename.view.php and yourgamename yourgamename.tpl 0 98 1879 685 2016-06-25T20:04:25Z Apollo1001 9584 /* Variables */ wikitext text/x-wiki These 2 files work together to provide the HTML layout of your game. Using these 2 files, you specify what HTML is rendered in your game client interface. In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser. Example: extract of "hearts_hearts.tpl": <pre> <div id="myhand_wrap" class="whiteblock"> <h3>{MY_HAND}</h3> <div id="myhand"> </div> </div> </pre> == WARNING == Your view and your template are supposed to generate only the BASE layout of the game You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :) Example of things to generate in your view: * The overall layout of your game interface (what is displayed where). * The board and fixed elements on the board (ex: places for cards, squares, ...). Example of things that shouldn't be generate by your view: * Game elements that come and go from the game area. * Game elements that are moving from one place to another. == phplib template system == BGA is using the phplib template system, used for example in PHPbb forums. More details about how to use phplib template system here: http://www.phpbuilder.com/columns/david20000512.php3 == Variables == In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value. In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}". To give a value to this variable in your view.php: Examples: <pre> // Display a translated version of "My hand" at the place of the variable in the template $this->tpl['MY_HAND'] = self::_("My hand"); // Display some raw HTML material at the place of the variable $this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" ); </pre> WARNING: do not use a variable called {id} as it will interfere with action buttons. == Blocks == Using "blocks", you can repeat a piece of HTML from your template several time. You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares: <pre> (in reversi_reversi.tpl) <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> <div id="discs"> </div> </div> (in reversi.view.php) $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Explanations: * You specify a block in your template file, using "BEGIN" and "END" keywords. In the example above, we are creating a block named "square". * In your view, you declare your block using "begin_block" method. * Then, you can insert as many block as you want to, using "insert_block" method. The insert_block method takes 2 parameters: * the name of the block to insert. * an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP). == Nested blocks == You can use nested blocks. In the example below, we are going to add a mini-board for each player of the game, with 4 card places on each of it: <pre> (In template file) <!-- BEGIN player --> <div class="miniboard" id="miniboard_{PLAYER_ID}"> <div class="card_places"> <!-- BEGIN card_place --> <div id="card_place_{PLAYER_ID}_{PLACE_ID}"> </div> <!-- END card_place --> </div> </div> <!-- END player --> (In view file) $this->page->begin_block( "mygame_mygame.tpl", "card_place" ); // Nested block must be declared first $this->page->begin_block( "mygame_mygame.tpl", "player" ); foreach( $players as $player_id => $player ) { // Important: nested block must be reset here, otherwise the second player miniboard will // have 8 card_place, the third will have 12 card_place, and so one... $this->page->reset_subblocks( 'card_place' ); for( $i=1; $i<=4; $i++ ) { $this->page->insert_block( "card_place", array( 'PLAYER_ID' => $player_id, 'PLACE_ID' => $i ); } $this->page->insert_block( 'player', array( 'PLAYER_ID' => $player_id ); } </pre> == Javascript templates == For game elements that come and go from the game area, we suggest you to define a Javascript template. A Javascript template is defined in your template file like this: (Reversi Token from Reversi example): <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: a section for javascript templates is already available at the end of your template skeleton file. Then, you can use this javascript template to insert this piece of HTML in your game interface, like this: <pre> dojo.place( this.format_block( 'jstpl_disc', { xy: x+''+y, color: color } ) , 'discs' ); </pre> == How to access game information from .view.php? == From your .view.php, you can access the following: === Access current player id=== <pre> global $g_user; $current_player_id = $g_user->get_id(); </pre> === Access game object === In your view file, "$this->game" contains an instance of your main game class. Example: <pre> // Access to some game elements description described in your "material.inc.php": $my_cards_types = $this->game->card_types; // Access to any (public) method defined in my .game.php file: $result = $this->game->myMethod(); </pre> == Tips: displaying a nice button == From time to time, you need to display a standard button in your interface. BGA framework provides you a standard button that you can use directly in your interface: <pre> <a href="#" id="my_button_id" class="button"><span>My button label</span></a> </pre> Note: To see it in action, check for example a Coloretto game e9cd5538c7cfefdab315438c0cfe852bd2c5af20 Gamehelpxiangqi 0 221 1882 2016-07-15T12:13:17Z 333-blue 13923 Created page with "&nbsp;" wikitext text/x-wiki &nbsp; 47c1f11ed4d1aad1a1b674bda71a89d4ff562d55 Gamehelppuertorico 0 23 1883 1843 2016-07-15T12:58:53Z Ckhiew 12887 wikitext text/x-wiki == Goal == Be the player with the most victory points at the end of the game by collecting: * victory points earned for buildings * victory point tokens earned at the captain phase * conditional victory points earned at the end of the game for occupied large buildings In case of a tie, the player owning the most doubloons and goods is the winner. == Rules summary == The game is played over several rounds. At the start of a round, the governor selects a role, then each player in turn selects a role. At the end of the round, the governor token moves to the next player. When a role has been chosen, each player in turn plays the action for this role. Only the player who selected the role can use the role privilege. Available roles are the following: * '''Mayor''': colonists set foot in the new world ! <br />''Privilege'': the mayor can get one more colonist from the supply. <br />''Action'': in turn, begining with the mayor, players get one colonist from the ship, until it is empty. Then players have to set colonists on their buildings and plantations. * '''Craftsman''': goods are produced. <br />''Privilege'': the craftsman can produce one more good of his choice. <br />''Action'': produce goods for your occupied buildings and plantations. * '''Trader''': goods are sold to the trading house. <br />''Privilege'': the trader earns 1 extra doubloon if he sells.<br />''Action'': sell one good the trading house doesn't have yet. * '''Settler''': plantations settlement. <br />''Privilege'': the settler can get a quarry instead of a plantation.<br />''Action'': get a plantation chosen among those available. * '''Builder''': buildings are bought and built. <br />Privilege: the builder can get a building for 1 doubloon less than the regular price. <br />Action: get a building chosen among those available. * '''Captain''': victory points are won by shipping goods to the old world. <br />''Privilege'': the captain earns one extra victory points if he ships some goods. <br />''Action'': select a type of good to load on a cargo ship; 1 victory point is earned for each barrel of this type of good loaded on the ship. * '''Prospector''': gold rush brings money! <br />''Privilege'': the prospector gets one doubloon from the bank. <br />''Action'': none. Please also note that occupied violet buildings have modifier effects for role actions. End of game happens at the end of the round for which one of the following events comes to pass: * there is not enough colonists in the supply to refill the colonist ship at the end of the mayor phase (the number of colonists refilled equals to the total number of unoccupied circles on each player's buildings, at the end of each round) * the last victory point token has been earned during the captain phase * at least one of the players built on his 12th and last free space in the city. == Playing online == Choosing a role : click on the role of your choice in the list on the right of your game board. * '''Mayor''': accept or refuse to get an extra colonist from the supply. Colonists are then automatically recruited by players. Click on a building or a plantation to setup a colonist on it. Click on a colonist to send it back to San Juan (the counter for colonists in San Juan is situated in your player panel on the right of the page). * '''Craftsman''': goods production is automated (counters for goods owned are in the player panel on the right of the page). Then, choose one extra good that you can produce as your privilege. * '''Trader''': choose a good that you want to sell by clicking on the appropriate counter in your player panel. * '''Settler''': click on the plantation (or quarry) that you want. Placement on your board is automated. * '''Builder''': click on the building that you want to buy. Placement on your board is automated. * '''Captain''': click on the cargo boat on which you want to ship some goods. Then choose the type of good that you want to ship by clicking on the appropriate counter in your player panel. At the end of the captain phase, if you have some goods to store (warehouse or windrose), click on the corresponding counter. Stored goods will be highlighted by a red frame. * '''Prospector''': doubloon is earned immediately. Tooltips are available to give information on roles and buildings by hovering over game elements with the mouse. == 'Balanced game' variant == This variant implements two game balance fixes giving each player an equal chance of winning as listed in the [http://en.wikipedia.org/wiki/Puerto_Rico_%28board_game%29 Puerto Rico (board game) Wikipedia page]. * The prices of the Factory and University buildings are swapped so that the Factory costs 8 doubloons and the University costs 7 doubloons * Any player that starts with a corn plantation starts with 1 doubloon less than the players that start with an indigo plantation. == Two players variant == Craftsman Angst : if this variant is selected, players alternate selecting a role as usual, until the Governor has selected '''three''' roles and the opponent has selected '''two''' roles (instead of three in a classic two players game), then the governor token goes to the opponent and a new round starts. This variant avoids the consecutive selection of two roles by the same player which happens on a change of round with the classic two player game rules. This variant is described on [http://www.boardgamegeek.com/thread/679955/the-craftsman-angst-variant-the-most-popular-revis Board Game Geek]. '''Have a good game !''' bc54e5768d7be7ca80fa667d39671507cbd0baa8 Gamehelptashkalar 0 177 1884 1811 2016-07-15T15:48:33Z Nandblock 11082 wikitext text/x-wiki == '''HIGH FORM RULES''' == == Terminology == Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any existing piece on the destination square of a valid move/leap is destroyed. You may destroy your own pieces. == Setup == Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). == Turns == Each player takes two of the following actions per turn: # Place a common piece on an empty square # Summon a being # Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: # You may claim one task card and earn its VPs if you meet its conditions. # If necessary, replenish your hand and update the task queue. == Playing a Flare == Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. == Summoning == If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. == Discarding == Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. == Running Out of Pieces == If a player needs to place a piece and has no more in stock, they must pick up one of those pieces on the board. == Game End and Scoring == When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == Modalità di gioco == Su Board Game Arena, Tash-Kalar può essere giocato da 2 a 4 giocatori e in 2 distinte modalità: - '''"Forma Suprema":''' I giocatori realizzano punti quando completano un obiettivo corrente e per i pezzi leggendari presenti nell'Arena. Questa modalità è disponibile solo per 2 giocatori. - '''"Duello Mortale"''': Non ci sono obiettivi da completare. I giocatori realizzano punti distruggendo pedine nemiche, evocando creature leggendarie e quando l'avversario invoca una carta impeto. il Duello Mortale può essere giocato da 2 a 4 giocatori. Il gioco in scatola prevede anche modalità a squadra in entrambe le modalità. == Setup == Ogni giocatore inizia con 6 carte pescate a caso: 3 esseri del proprio mazzo, 2 leggendari e 1 impeto. Nella modalità '''"Forma Suprema"''', vengono rivelati 3 obiettivi correnti più 1 come prossimo obiettivo. Nella modalità '''"Duello Mortale"''', il giocatore che gioca per secondo piazza 1 pezzo comune di ogni colore nei quadrati marcati dell'Arena. == Game play == Si comincia dal primo giocatore scelto a caso e si procede in senso orario. Ogni turno prevede 2 azioni, tranne il giocatore iniziale che ha solo 1 azione disponibile come primo turno. Azioni possibili: - '''"Piazzare 1 pezzo semplice"''' del tuo colore su un quadrato vuoto. Se non hai pezzi disponibili devi riprendere 1 dei tuoi pezzi semplici o eroici già piazzati sull'Arena in precedenza e dopo piazzarlo dove vuoi. - '''"Evocare una cretura"'''. Leggi più avanti - '''"Scartare 1 carta creatura del tuo mazzo"'''. Se lo fai puoi anche mettere una o più carte (anche leggendarie o impeti) in fondo al rispettivo mazzo di pesca. Le azioni possono essere eseguite in qualsiasi ordine. Puoi prima "piazzare" e poi "evocare" o viceversa (puoi fare una sola azione di scarto per turno). Devi sempre usare le tue azioni disponibili. Puoi invocare un impeto (leggi più avanti) prima o dopo un'azione. Invocare un impeto non costa nessuna azione. Il tuo turno finisce pescando altrettante carte di quante ne sono state giocate, in modo da avere sempre 3 carte creatura del tuo mazzo, 2 leggendarie e 1 impeto. Se peschi l'ultima carta del tuo mazzo, potresti finire la partita anche con meno di 3 carte creatura in mano. '''"Forma Suprema"''': Alla fine del tuo turno puoi completare solamente 1 dei compiti disponibili, se hai soddisfatto i suoi requisiti. '''"Duello Mortale"''': Alla fine del tuo turno, realizzi punti per le pedine nemiche distrutte: 2 punti per una leggendaria, 1 punto per un'eroica e 1 punto per ogni coppia di pedine semplici distrutte. Nella ''Mischia Mortale'' (3-4 giocatori) fai punti per ogni pedina nemica distrutta nei diversi colori. Il tuo punteggio finale è determinato dal colore nel quale hai il punteggio più basso. Non realizzi punti se distruggi tue pedine e per tutte le pedine semplici nemiche spaiate di un solo colore. Puoi appaiare 2 pedine semplici nemiche di diverso colore e decidere in quale colore realizzare i punti. Realizzi 1 punto (nel colore che preferisci) ogni volta che evochi 1 leggenda (promuovere un pezzo eroico non conta come un'evocazione leggendaria). Se il tuo avversario invoca 1 carta impeto tu guadagni 1 punto. == Evocare una creatura == Per evocare una creatura, usa 1 azione in questo modo: - '''"Gioca una carta"''' dalla tua mano e scegli il quadrato sull'Arena che soddisfi la forma del pattern (schema) richiesto sulla carta. Lo schema può essere ruotato (a 90, 180 o 270 gradi), specchiato e/o capovolto. I pezzi usati per evocare la creatura devono essere dello stesso grado (o maggiore) riportato sulla carta. I quadrati vuoti non sono essenziali per evocare la creatura. - '''"Piazza un pezzo del grado indicato"''' (in alto a sinistra sulla carta) sul quadrato marcato di bianco nello schema. Questo quadrato può essere vuoto, a meno che lo schema non specifichi che debba essere occupato da un vostro pezzo. Se il quadrato è occupato da un pezzo dello stesso grado o inferiore, distruggilo, mettendo il nuovo pezzo al suo posto. Se il quadrato è occupato da un pezzo di grado superiore non puoi evocare l'essere in quel quadrato. Se tutti i pezzi di quel tipo sono già piazzati sull'Arena, puoi riprenderne uno di quelli non richiesti dal pattern in questione. - Quando il nuovo pezzo è piazzato sull'Arena '''"risolvi i suoi effetti"''' scritti sulla carta. - Dopo aver risolto gli effetti, scarta la carta. == Invocare un Impeto == Puoi invocare una carta impeto durnte il tuo turno prima o dopo una qualsiasi azione. Per invocare l'impeto devi soddisfare almeno uno dei due criteri scritti sulla carta: - Soddisfi il criterio stampato in alto sulla carta se il tuo avversario ha almeno quel numero di pezzi promossi (eroici e leggendari) più di te nell'Arena. - Soddisfi il criterio stampato in basso sulla carta se il tuo avversario ha almeno quel numero di pezzi totali (semplici, eroici e leggendari) più di te nell'Arena. Se si verificano una o tutte e due condizioni scritte sulla carta puoi risolverne gli effetti. Se soddisfi i criteri contro più avversari scegli contro chi comparare la carta (e quindi assegnare l'eventuale punto nei Duelli Mortali). Una volta che la carta è stata utilizzata bisogna scartarla. == Risolvere gli effetti delle creature e degli Impeti == Nessun'altra azione (anche invocare impeti) può essere intrapresa fino a che l'intero effetto di una carta non sia stato risolto. Alcune parti di un effetto possono essere opzionali: - '''"Puoi"''' indica che una certa parte dell'effetto è opzionale. - '''"Fino a"''' include sempre lo zero. Le parti che non sono specifcate come opzionali sono obbligatorie. Se un effetto non può essere risolto per intero, risolvi solo le parti disponibili. Quando una carta si riferisce al nome della creatura, si riferisce direttamente al pezzo che in quella azione rappresenta la creatura evocata. '''Keywords''': - '''Pezzo promosso:''' un pezzo eroico o leggendario. - '''Pezzo non leggendario:''' Un pezzo comune o eroico. - '''Pezzo:''' Se un pezzo non è specificato se appartiene a te o al tuo avversario, fa riferimento a tutti i pezzi (inclusi i tuoi). - '''Spazio marcato:''' Uno spazio colorato nel pattern. Se il testo della carta non si riferisce al quadrato marcato, i quadrati marcati del pattern sono solo illustrativi. - '''Quadrato adiacente:''' Uno degli otto quadrati adiacenti sia ortogonalmente che diagonalmente ad un determinato pezzo o quadrato. Se il quadrato di riferimento non è specificato, fa riferimento al quadrato occupato dalla nuova creatura evocata. - '''Distanza:''' Il numero di mosse richieste da un quadrato ad un altro. Per esempio, un quadrato adiacente è a distanza 1. - '''Mossa:''' Una mossa è sempre su un quadrato adiacente. Una mossa in un quadrato occupato, distrugge il pezzo presente. - '''Mossa Standard o Normale:''' Questo tipo di mossa può essere fatta solo su quadrati vuoti o su quadrati occupati da pezzi di grado inferiore. - '''Mossa di Combattimento:''' Questo tipo di mossa può essere fatta solo su quadrati vuoti o su quadrati occupati da pezzi di grado uguale o inferiore. - '''Salto normale e Salto di combattimento:''' Un salto è come una mossa con la differenza che il quadrato di destinazione può non essere adiacente. Se non specificato diversamente, il salto può essere fatto su qualsiasi quadrato nell'Arena. - '''Piazza:''' Come l'azione "Piazzare", a differenza che se non ci sono pezzi disponibili di quel colore e grado, il pezzo non può essere piazzato. - '''Promuovi:''' I pezzi leggendari non possono essere promossi. Per promuovere un pezzo comune, giralo. Per promuovere un pezzo eroico rimpiazzalo con uno leggendario. Se i leggendari non sono più disponibili, il pezzo eroico non può essere promosso. - '''Degrada:''' I pezzi comuni non possono essere degradati. Per degradare un pezzo eroico, giralo dal lato comune. Per degradare un pezzo leggendario rimpiazzalo con uno eroico. Se non ci sono pezzi eroici disponibili, il leggendario non può essere degradato. - '''Distruggi:''' Per distruggere un pezzo, rimuovilo dall'Arena. - '''Converti:''' Per convertire un pezzo nemico, rimpiazzalo con uno dei tuoi pezzi dello stesso grado (a meno che non specificato diversamente). Quando bisogna tenere traccia di '''"quanti pezzi nemici hai distrutto"''', conta i pezzi nemici che hai distrutto durante l'evocazione, mosse o salti, pezzi distrutti per "effetti di distruzione" e pezzi convertiti. Nè la promozione nè il degradamento contano come pezzi distrutti. == Fine del Gioco == La fine del gioco è innescata quando un giocatore pesca l'ultima carta dal suo mazzo di creature. Nella modalità '''"Forma Suprema"''', la fine del gioco è innescata anche quando un giocatore raggiunge o supera 9 punti alla fine del suo turno. Conta i punti degli obiettivi completati (dal giocatore o dalla squadra) più 1 punto per ogni pezzo leggendario presente sull'Arena (non importa se sia stato evocato o promosso) Nel '''"Duello Mortale"''', la fine del gioco è innescata anche quando un giocatore raggiunge o supera 18 punti. Quando la fine del gioco è stata innescata, i giocatori giocheranno un solo turno a testa, incluso il giocatore che ha innescato la fine del gioco. Dopo gli ultimi turni il gioco finisce e il giocatore con più punti vince. Se c'è un pareggio, viene risolto in questo modo: - Vince chi ha più pezzi promossi nell'Arena; - In caso di ulteriore pareggio, vince chi ha il numero maggiore di pezzi totali nell'Arena; - In caso di ulteriore pareggio, il gioco è da considerarsi pari. ---- Queste regole sono un estratto del regolamento ufficiale di Tash-Kalar della CGE. 25e4017f6f9b6652e54031893dc6519b63170dad 1885 1884 2016-07-15T16:05:52Z Nandblock 11082 wikitext text/x-wiki == '''HIGH FORM RULES''' == == Terminology == Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any existing piece on the destination square of a valid move/leap is destroyed. You may destroy your own pieces. == Setup == Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). == Turns == Each player takes two of the following actions per turn: # Place a common piece on an empty square # Summon a being # Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: # You may claim one task card and earn its VPs if you meet its conditions. # If necessary, replenish your hand and update the task queue. == Playing a Flare == Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. == Summoning == If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. == Discarding == Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. == Running Out of Pieces == If a player needs to place a piece and has no more in stock, they must pick up one of those pieces on the board. == Game End and Scoring == When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 points triggers the endgame. Destroying pieces scores points as follows: * 1 point for every 2 common pieces, rounded down * 1 point for a heroic piece * 2 points for a legendary piece Summoning a legend scores 1 point. (The point is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 point. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicbable third lowest scores are used as tiebreakers.) Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. == Improvised Summoning == Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) 10b8fd195566dc91cc111e8c3eec07d72b348f5f 1887 1885 2016-07-15T16:07:32Z Nandblock 11082 /* Running Out of Pieces */ wikitext text/x-wiki == '''HIGH FORM RULES''' == == Terminology == Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any existing piece on the destination square of a valid move/leap is destroyed. You may destroy your own pieces. == Setup == Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). == Turns == Each player takes two of the following actions per turn: # Place a common piece on an empty square # Summon a being # Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: # You may claim one task card and earn its VPs if you meet its conditions. # If necessary, replenish your hand and update the task queue. == Playing a Flare == Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. == Summoning == If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. == Discarding == Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. == Running Out of Pieces == If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. == Game End and Scoring == When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 points triggers the endgame. Destroying pieces scores points as follows: * 1 point for every 2 common pieces, rounded down * 1 point for a heroic piece * 2 points for a legendary piece Summoning a legend scores 1 point. (The point is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 point. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicbable third lowest scores are used as tiebreakers.) Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. == Improvised Summoning == Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) d557a091a7eac3fb28720f9ba4850727d8187238 1888 1887 2016-07-15T16:08:00Z Nandblock 11082 /* Turns */ wikitext text/x-wiki == '''HIGH FORM RULES''' == == Terminology == Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any existing piece on the destination square of a valid move/leap is destroyed. You may destroy your own pieces. == Setup == Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). == Turns == Each player takes two of the following actions per turn: # Place a common piece on an empty square # Summon a being # Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: # You may claim one task card and earn its VPs if you meet its conditions. # If necessary, replenish your hand from the appropriate decks and update the task queue. == Playing a Flare == Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. == Summoning == If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. == Discarding == Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. == Running Out of Pieces == If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. == Game End and Scoring == When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 points triggers the endgame. Destroying pieces scores points as follows: * 1 point for every 2 common pieces, rounded down * 1 point for a heroic piece * 2 points for a legendary piece Summoning a legend scores 1 point. (The point is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 point. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicbable third lowest scores are used as tiebreakers.) Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. == Improvised Summoning == Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) f753e1c3f12ee6f4b24dd649a8b1c9a31ce692e9 1889 1888 2016-07-15T16:08:20Z Nandblock 11082 /* Turns */ wikitext text/x-wiki == '''HIGH FORM RULES''' == == Terminology == Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any existing piece on the destination square of a valid move/leap is destroyed. You may destroy your own pieces. == Setup == Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). == Turns == Each player takes two of the following actions per turn: # Place a common piece on an empty square # Summon a being # Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: # You may claim one task card and earn its VPs if you meet its conditions. # If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) == Playing a Flare == Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. == Summoning == If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. == Discarding == Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. == Running Out of Pieces == If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. == Game End and Scoring == When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 points triggers the endgame. Destroying pieces scores points as follows: * 1 point for every 2 common pieces, rounded down * 1 point for a heroic piece * 2 points for a legendary piece Summoning a legend scores 1 point. (The point is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 point. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicbable third lowest scores are used as tiebreakers.) Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. == Improvised Summoning == Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) e4adf9105fdd168d0fb264a35eb383c6419e8615 1890 1889 2016-07-15T16:08:51Z Nandblock 11082 /* Terminology */ wikitext text/x-wiki == '''HIGH FORM RULES''' == == Terminology == Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any existing piece on the destination square of a valid move/leap is destroyed. You may destroy your own pieces. == Setup == Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). == Turns == Each player takes two of the following actions per turn: # Place a common piece on an empty square # Summon a being # Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: # You may claim one task card and earn its VPs if you meet its conditions. # If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) == Playing a Flare == Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. == Summoning == If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. == Discarding == Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. == Running Out of Pieces == If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. == Game End and Scoring == When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 points triggers the endgame. Destroying pieces scores points as follows: * 1 point for every 2 common pieces, rounded down * 1 point for a heroic piece * 2 points for a legendary piece Summoning a legend scores 1 point. (The point is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 point. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicbable third lowest scores are used as tiebreakers.) Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. == Improvised Summoning == Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) 8f684d77f8554bb78936ddded6555231339d323a 1891 1890 2016-07-15T16:09:21Z Nandblock 11082 /* DEATHMATCH RULES: THREE OR FOUR PLAYERS */ wikitext text/x-wiki == '''HIGH FORM RULES''' == == Terminology == Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any existing piece on the destination square of a valid move/leap is destroyed. You may destroy your own pieces. == Setup == Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). == Turns == Each player takes two of the following actions per turn: # Place a common piece on an empty square # Summon a being # Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: # You may claim one task card and earn its VPs if you meet its conditions. # If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) == Playing a Flare == Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. == Summoning == If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. == Discarding == Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. == Running Out of Pieces == If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. == Game End and Scoring == When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 points triggers the endgame. Destroying pieces scores points as follows: * 1 point for every 2 common pieces, rounded down * 1 point for a heroic piece * 2 points for a legendary piece Summoning a legend scores 1 point. (The point is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 point. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. == Improvised Summoning == Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) a9a2d46b88ae452cb5ba69f889934753c1ae765d 1892 1891 2016-07-15T16:10:06Z Nandblock 11082 /* Terminology */ wikitext text/x-wiki == '''HIGH FORM RULES''' == == Terminology == Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any already existing piece on the destination square of a valid move/leap is destroyed. You may destroy your own pieces. == Setup == Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). == Turns == Each player takes two of the following actions per turn: # Place a common piece on an empty square # Summon a being # Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: # You may claim one task card and earn its VPs if you meet its conditions. # If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) == Playing a Flare == Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. == Summoning == If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. == Discarding == Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. == Running Out of Pieces == If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. == Game End and Scoring == When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 points triggers the endgame. Destroying pieces scores points as follows: * 1 point for every 2 common pieces, rounded down * 1 point for a heroic piece * 2 points for a legendary piece Summoning a legend scores 1 point. (The point is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 point. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. == Improvised Summoning == Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) 678ea0c2792d0e9ade0f8c2f5d054f7fd698c058 1893 1892 2016-07-15T16:10:32Z Nandblock 11082 /* Terminology */ wikitext text/x-wiki == '''HIGH FORM RULES''' == == Terminology == Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously on the destination square of a valid move/leap is destroyed. You may destroy your own pieces. == Setup == Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). == Turns == Each player takes two of the following actions per turn: # Place a common piece on an empty square # Summon a being # Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: # You may claim one task card and earn its VPs if you meet its conditions. # If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) == Playing a Flare == Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. == Summoning == If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. == Discarding == Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. == Running Out of Pieces == If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. == Game End and Scoring == When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 points triggers the endgame. Destroying pieces scores points as follows: * 1 point for every 2 common pieces, rounded down * 1 point for a heroic piece * 2 points for a legendary piece Summoning a legend scores 1 point. (The point is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 point. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. == Improvised Summoning == Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) 828179dc18929a851ff1c31a198cecfbb5a669c6 1894 1893 2016-07-15T16:10:46Z Nandblock 11082 /* Terminology */ wikitext text/x-wiki == '''HIGH FORM RULES''' == == Terminology == Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a valid move/leap is destroyed. You may destroy your own pieces. == Setup == Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). == Turns == Each player takes two of the following actions per turn: # Place a common piece on an empty square # Summon a being # Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: # You may claim one task card and earn its VPs if you meet its conditions. # If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) == Playing a Flare == Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. == Summoning == If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. == Discarding == Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. == Running Out of Pieces == If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. == Game End and Scoring == When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 points triggers the endgame. Destroying pieces scores points as follows: * 1 point for every 2 common pieces, rounded down * 1 point for a heroic piece * 2 points for a legendary piece Summoning a legend scores 1 point. (The point is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 point. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. == Improvised Summoning == Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) 6289009f66278e526f2c7f0efc5faff6a0f9c175 1895 1894 2016-07-15T16:17:21Z Nandblock 11082 wikitext text/x-wiki == '''HIGH FORM RULES''' == === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a valid move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === Each player takes two of the following actions per turn: # Place a common piece on an empty square # Summon a being # Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: # You may claim one task card and earn its VPs if you meet its conditions. # If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. === Game End and Scoring === When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 points triggers the endgame. Destroying pieces scores points as follows: * 1 point for every 2 common pieces, rounded down * 1 point for a heroic piece * 2 points for a legendary piece Summoning a legend scores 1 point. (The point is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 point. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. === Improvised Summoning === Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) 01ee3d27c0968de2df75d0991befef62f25dac32 1896 1895 2016-07-15T16:19:50Z Nandblock 11082 /* HIGH FORM RULES */ wikitext text/x-wiki == '''HIGH FORM RULES''' == === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === Each player takes two of the following actions per turn: # Place a common piece on an empty square # Summon a being # Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: # You may claim one task card and earn its VPs if you meet its conditions. # If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. === Game End and Scoring === When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 points triggers the endgame. Destroying pieces scores points as follows: * 1 point for every 2 common pieces, rounded down * 1 point for a heroic piece * 2 points for a legendary piece Summoning a legend scores 1 point. (The point is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 point. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. === Improvised Summoning === Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) 4c2e34ac7adeb816aee514fab4e84765cc24fc44 1897 1896 2016-07-15T16:24:30Z Nandblock 11082 /* HIGH FORM RULES */ wikitext text/x-wiki There are two forms of Tash-Kalar: High Form, in which points are scored by completing tasks; and Deathmatch, in which points are scored by destroying opponents' pieces. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. == '''HIGH FORM RULES''' == === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === Each player takes two of the following actions per turn: # Place a common piece on an empty square # Summon a being # Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: # You may claim one task card and earn its VPs if you meet its conditions. # If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. === Game End and Scoring === When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 points triggers the endgame. Destroying pieces scores points as follows: * 1 point for every 2 common pieces, rounded down * 1 point for a heroic piece * 2 points for a legendary piece Summoning a legend scores 1 point. (The point is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 point. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. === Improvised Summoning === Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) 5c450780a1160c3fdc03516b92ad2e47beb99ca3 1898 1897 2016-07-15T16:48:46Z Nandblock 11082 wikitext text/x-wiki == '''HIGH FORM RULES''' == === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === Each player takes two of the following actions per turn: # Place a common piece on an empty square # Summon a being # Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: # You may claim one task card and earn its VPs if you meet its conditions. # If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. === Game End and Scoring === When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 points triggers the endgame. Destroying pieces scores points as follows: * 1 point for every 2 common pieces, rounded down * 1 point for a heroic piece * 2 points for a legendary piece Summoning a legend scores 1 point. (The point is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 point. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. === Improvised Summoning === Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) 4c2e34ac7adeb816aee514fab4e84765cc24fc44 1899 1898 2016-07-15T19:34:20Z Nandblock 11082 wikitext text/x-wiki == '''HIGH FORM RULES''' == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === Each player takes two of the following actions per turn: * - Place a common piece on an empty square * - Summon a being * - Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its VPs if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. === Game End and Scoring === When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 points triggers the endgame. Destroying pieces scores points as follows: * - 1 point for every 2 common pieces, rounded down * - 1 point for a heroic piece * - 2 points for a legendary piece Summoning a legend scores 1 point. (The point is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 point. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) When you score common pieces, first all pairs of common colours are scored; then, if there are two common pieces of different colours left over, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 point). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. === Improvised Summoning === Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) 66cf4e757ad132d2df050f22a33cf9b402c75b82 1900 1899 2016-07-15T19:35:35Z Nandblock 11082 /* DEATHMATCH RULES: THREE OR FOUR PLAYERS */ wikitext text/x-wiki == '''HIGH FORM RULES''' == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === Each player takes two of the following actions per turn: * - Place a common piece on an empty square * - Summon a being * - Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its VPs if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. === Game End and Scoring === When one player scores 9 points or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 points triggers the endgame. Destroying pieces scores points as follows: * - 1 point for every 2 common pieces, rounded down * - 1 point for a heroic piece * - 2 points for a legendary piece Summoning a legend scores 1 point. (The point is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 point. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. === Improvised Summoning === Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) 0a4e42abe5b81fcaba24fb96f2e3897d8897bbe3 1901 1900 2016-07-15T19:37:04Z Nandblock 11082 wikitext text/x-wiki == '''HIGH FORM RULES''' == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === Each player takes two of the following actions per turn: * - Place a common piece on an empty square * - Summon a being * - Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its victory points (VPs) if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. === Game End and Scoring === When one player scores 9 VPs or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 VPs triggers the endgame. Destroying pieces scores VPs as follows: * - 1 VP for every 2 common pieces, rounded down * - 1 VP for a heroic piece * - 2 VPs for a legendary piece Summoning a legend scores 1 VP. (The VP is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 VP. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. === Improvised Summoning === Once per game, each player is permitted to use one piece of each opponent as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) 7b874f8551f066a58815d090562a12e3dc89487b Kaozeal:Gamehelptashkalar 1 222 1886 2016-07-15T16:06:50Z Nandblock 11082 Created page with "I deleted the long set of rules in Italian, as a shorter document in English seemed more helpful: they were as follows: == Modalità di gioco == Su Board Game Arena, Tash..." wikitext text/x-wiki I deleted the long set of rules in Italian, as a shorter document in English seemed more helpful: they were as follows: == Modalità di gioco == Su Board Game Arena, Tash-Kalar può essere giocato da 2 a 4 giocatori e in 2 distinte modalità: - '''"Forma Suprema":''' I giocatori realizzano punti quando completano un obiettivo corrente e per i pezzi leggendari presenti nell'Arena. Questa modalità è disponibile solo per 2 giocatori. - '''"Duello Mortale"''': Non ci sono obiettivi da completare. I giocatori realizzano punti distruggendo pedine nemiche, evocando creature leggendarie e quando l'avversario invoca una carta impeto. il Duello Mortale può essere giocato da 2 a 4 giocatori. Il gioco in scatola prevede anche modalità a squadra in entrambe le modalità. == Setup == Ogni giocatore inizia con 6 carte pescate a caso: 3 esseri del proprio mazzo, 2 leggendari e 1 impeto. Nella modalità '''"Forma Suprema"''', vengono rivelati 3 obiettivi correnti più 1 come prossimo obiettivo. Nella modalità '''"Duello Mortale"''', il giocatore che gioca per secondo piazza 1 pezzo comune di ogni colore nei quadrati marcati dell'Arena. == Game play == Si comincia dal primo giocatore scelto a caso e si procede in senso orario. Ogni turno prevede 2 azioni, tranne il giocatore iniziale che ha solo 1 azione disponibile come primo turno. Azioni possibili: - '''"Piazzare 1 pezzo semplice"''' del tuo colore su un quadrato vuoto. Se non hai pezzi disponibili devi riprendere 1 dei tuoi pezzi semplici o eroici già piazzati sull'Arena in precedenza e dopo piazzarlo dove vuoi. - '''"Evocare una cretura"'''. Leggi più avanti - '''"Scartare 1 carta creatura del tuo mazzo"'''. Se lo fai puoi anche mettere una o più carte (anche leggendarie o impeti) in fondo al rispettivo mazzo di pesca. Le azioni possono essere eseguite in qualsiasi ordine. Puoi prima "piazzare" e poi "evocare" o viceversa (puoi fare una sola azione di scarto per turno). Devi sempre usare le tue azioni disponibili. Puoi invocare un impeto (leggi più avanti) prima o dopo un'azione. Invocare un impeto non costa nessuna azione. Il tuo turno finisce pescando altrettante carte di quante ne sono state giocate, in modo da avere sempre 3 carte creatura del tuo mazzo, 2 leggendarie e 1 impeto. Se peschi l'ultima carta del tuo mazzo, potresti finire la partita anche con meno di 3 carte creatura in mano. '''"Forma Suprema"''': Alla fine del tuo turno puoi completare solamente 1 dei compiti disponibili, se hai soddisfatto i suoi requisiti. '''"Duello Mortale"''': Alla fine del tuo turno, realizzi punti per le pedine nemiche distrutte: 2 punti per una leggendaria, 1 punto per un'eroica e 1 punto per ogni coppia di pedine semplici distrutte. Nella ''Mischia Mortale'' (3-4 giocatori) fai punti per ogni pedina nemica distrutta nei diversi colori. Il tuo punteggio finale è determinato dal colore nel quale hai il punteggio più basso. Non realizzi punti se distruggi tue pedine e per tutte le pedine semplici nemiche spaiate di un solo colore. Puoi appaiare 2 pedine semplici nemiche di diverso colore e decidere in quale colore realizzare i punti. Realizzi 1 punto (nel colore che preferisci) ogni volta che evochi 1 leggenda (promuovere un pezzo eroico non conta come un'evocazione leggendaria). Se il tuo avversario invoca 1 carta impeto tu guadagni 1 punto. == Evocare una creatura == Per evocare una creatura, usa 1 azione in questo modo: - '''"Gioca una carta"''' dalla tua mano e scegli il quadrato sull'Arena che soddisfi la forma del pattern (schema) richiesto sulla carta. Lo schema può essere ruotato (a 90, 180 o 270 gradi), specchiato e/o capovolto. I pezzi usati per evocare la creatura devono essere dello stesso grado (o maggiore) riportato sulla carta. I quadrati vuoti non sono essenziali per evocare la creatura. - '''"Piazza un pezzo del grado indicato"''' (in alto a sinistra sulla carta) sul quadrato marcato di bianco nello schema. Questo quadrato può essere vuoto, a meno che lo schema non specifichi che debba essere occupato da un vostro pezzo. Se il quadrato è occupato da un pezzo dello stesso grado o inferiore, distruggilo, mettendo il nuovo pezzo al suo posto. Se il quadrato è occupato da un pezzo di grado superiore non puoi evocare l'essere in quel quadrato. Se tutti i pezzi di quel tipo sono già piazzati sull'Arena, puoi riprenderne uno di quelli non richiesti dal pattern in questione. - Quando il nuovo pezzo è piazzato sull'Arena '''"risolvi i suoi effetti"''' scritti sulla carta. - Dopo aver risolto gli effetti, scarta la carta. == Invocare un Impeto == Puoi invocare una carta impeto durnte il tuo turno prima o dopo una qualsiasi azione. Per invocare l'impeto devi soddisfare almeno uno dei due criteri scritti sulla carta: - Soddisfi il criterio stampato in alto sulla carta se il tuo avversario ha almeno quel numero di pezzi promossi (eroici e leggendari) più di te nell'Arena. - Soddisfi il criterio stampato in basso sulla carta se il tuo avversario ha almeno quel numero di pezzi totali (semplici, eroici e leggendari) più di te nell'Arena. Se si verificano una o tutte e due condizioni scritte sulla carta puoi risolverne gli effetti. Se soddisfi i criteri contro più avversari scegli contro chi comparare la carta (e quindi assegnare l'eventuale punto nei Duelli Mortali). Una volta che la carta è stata utilizzata bisogna scartarla. == Risolvere gli effetti delle creature e degli Impeti == Nessun'altra azione (anche invocare impeti) può essere intrapresa fino a che l'intero effetto di una carta non sia stato risolto. Alcune parti di un effetto possono essere opzionali: - '''"Puoi"''' indica che una certa parte dell'effetto è opzionale. - '''"Fino a"''' include sempre lo zero. Le parti che non sono specifcate come opzionali sono obbligatorie. Se un effetto non può essere risolto per intero, risolvi solo le parti disponibili. Quando una carta si riferisce al nome della creatura, si riferisce direttamente al pezzo che in quella azione rappresenta la creatura evocata. '''Keywords''': - '''Pezzo promosso:''' un pezzo eroico o leggendario. - '''Pezzo non leggendario:''' Un pezzo comune o eroico. - '''Pezzo:''' Se un pezzo non è specificato se appartiene a te o al tuo avversario, fa riferimento a tutti i pezzi (inclusi i tuoi). - '''Spazio marcato:''' Uno spazio colorato nel pattern. Se il testo della carta non si riferisce al quadrato marcato, i quadrati marcati del pattern sono solo illustrativi. - '''Quadrato adiacente:''' Uno degli otto quadrati adiacenti sia ortogonalmente che diagonalmente ad un determinato pezzo o quadrato. Se il quadrato di riferimento non è specificato, fa riferimento al quadrato occupato dalla nuova creatura evocata. - '''Distanza:''' Il numero di mosse richieste da un quadrato ad un altro. Per esempio, un quadrato adiacente è a distanza 1. - '''Mossa:''' Una mossa è sempre su un quadrato adiacente. Una mossa in un quadrato occupato, distrugge il pezzo presente. - '''Mossa Standard o Normale:''' Questo tipo di mossa può essere fatta solo su quadrati vuoti o su quadrati occupati da pezzi di grado inferiore. - '''Mossa di Combattimento:''' Questo tipo di mossa può essere fatta solo su quadrati vuoti o su quadrati occupati da pezzi di grado uguale o inferiore. - '''Salto normale e Salto di combattimento:''' Un salto è come una mossa con la differenza che il quadrato di destinazione può non essere adiacente. Se non specificato diversamente, il salto può essere fatto su qualsiasi quadrato nell'Arena. - '''Piazza:''' Come l'azione "Piazzare", a differenza che se non ci sono pezzi disponibili di quel colore e grado, il pezzo non può essere piazzato. - '''Promuovi:''' I pezzi leggendari non possono essere promossi. Per promuovere un pezzo comune, giralo. Per promuovere un pezzo eroico rimpiazzalo con uno leggendario. Se i leggendari non sono più disponibili, il pezzo eroico non può essere promosso. - '''Degrada:''' I pezzi comuni non possono essere degradati. Per degradare un pezzo eroico, giralo dal lato comune. Per degradare un pezzo leggendario rimpiazzalo con uno eroico. Se non ci sono pezzi eroici disponibili, il leggendario non può essere degradato. - '''Distruggi:''' Per distruggere un pezzo, rimuovilo dall'Arena. - '''Converti:''' Per convertire un pezzo nemico, rimpiazzalo con uno dei tuoi pezzi dello stesso grado (a meno che non specificato diversamente). Quando bisogna tenere traccia di '''"quanti pezzi nemici hai distrutto"''', conta i pezzi nemici che hai distrutto durante l'evocazione, mosse o salti, pezzi distrutti per "effetti di distruzione" e pezzi convertiti. Nè la promozione nè il degradamento contano come pezzi distrutti. == Fine del Gioco == La fine del gioco è innescata quando un giocatore pesca l'ultima carta dal suo mazzo di creature. Nella modalità '''"Forma Suprema"''', la fine del gioco è innescata anche quando un giocatore raggiunge o supera 9 punti alla fine del suo turno. Conta i punti degli obiettivi completati (dal giocatore o dalla squadra) più 1 punto per ogni pezzo leggendario presente sull'Arena (non importa se sia stato evocato o promosso) Nel '''"Duello Mortale"''', la fine del gioco è innescata anche quando un giocatore raggiunge o supera 18 punti. Quando la fine del gioco è stata innescata, i giocatori giocheranno un solo turno a testa, incluso il giocatore che ha innescato la fine del gioco. Dopo gli ultimi turni il gioco finisce e il giocatore con più punti vince. Se c'è un pareggio, viene risolto in questo modo: - Vince chi ha più pezzi promossi nell'Arena; - In caso di ulteriore pareggio, vince chi ha il numero maggiore di pezzi totali nell'Arena; - In caso di ulteriore pareggio, il gioco è da considerarsi pari. ---- Queste regole sono un estratto del regolamento ufficiale di Tash-Kalar della CGE. c42771fce78305c3bc8f8f72b5da917f05ca2de2 Gamehelptashkalar 0 177 1902 1901 2016-07-15T19:44:46Z Nandblock 11082 wikitext text/x-wiki == '''HIGH FORM RULES''' == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === Each player takes two of the following actions per turn: * - Place a common piece on an empty square * - Summon a being * - Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its victory points (VPs) if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. === Game End and Scoring === When one player scores 9 VPs or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 VPs triggers the endgame. Destroying pieces scores VPs as follows: * - 1 VP for every 2 common pieces, rounded down * - 1 VP for a heroic piece * - 2 VPs for a legendary piece Summoning a legend scores 1 VP. (The VP is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 VP. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. === Improvised Summoning === Once per game, and once for each opponent's colour, a player may use an opponent's piece as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) Only one piece may be used per improvised summoning: you can't use two different opponent's pieces simultaneously). 2eaf75c3db2652b19f5aaa2550dbc7bc0436a8f3 1903 1902 2016-07-15T19:50:03Z Nandblock 11082 /* HIGH FORM RULES */ wikitext text/x-wiki == '''HIGH FORM RULES''' == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === The starting player takes a turn consisting of a single action. In subsequent turns, each player takes two of the following actions per turn: * - Place a common piece on an empty square * - Summon a being * - Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its victory points (VPs) if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. === Game End and Scoring === When one player scores 9 VPs or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == EVERFROST EXPANSION == Several Beings in the Everfrost deck have "frozen effects". These are effects that do not have to take place immediately upon summoning; they can "frozen" and then activated later ("thawed"), like a flare. Only one such frozen effect may be stored up at a time; if you summon a Being with a frozen effect and already have one in storage, you must discard one of them. == '''DEATHMATCH RULES: TWO-PLAYER''' == No tasks are used. The first player to score 18 VPs triggers the endgame. Destroying pieces scores VPs as follows: * - 1 VP for every 2 common pieces, rounded down * - 1 VP for a heroic piece * - 2 VPs for a legendary piece Summoning a legend scores 1 VP. (The VP is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 VP. == '''DEATHMATCH RULES: THREE OR FOUR PLAYERS''' == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. === Improvised Summoning === Once per game, and once for each opponent's colour, a player may use an opponent's piece as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) Only one piece may be used per improvised summoning: you can't use two different opponent's pieces simultaneously). bb684f87c3ad484b61a0f78e510844820367b326 1904 1903 2016-07-15T19:51:11Z Nandblock 11082 wikitext text/x-wiki == HIGH FORM RULES == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === The starting player takes a turn consisting of a single action. In subsequent turns, each player takes two of the following actions per turn: * - Place a common piece on an empty square * - Summon a being * - Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its victory points (VPs) if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. === Game End and Scoring === When one player scores 9 VPs or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == DEATHMATCH RULES: TWO-PLAYERS (DUEL) == No tasks are used. The first player to score 18 VPs triggers the endgame. Destroying pieces scores VPs as follows: * - 1 VP for every 2 common pieces, rounded down * - 1 VP for a heroic piece * - 2 VPs for a legendary piece Summoning a legend scores 1 VP. (The VP is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 VP. == DEATHMATCH RULES: THREE OR FOUR PLAYERS == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. === Improvised Summoning === Once per game, and once for each opponent's colour, a player may use an opponent's piece as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) Only one piece may be used per improvised summoning: you can't use two different opponent's pieces simultaneously). == EVERFROST EXPANSION == Several Beings in the Everfrost deck have "frozen effects". These are effects that do not have to take place immediately upon summoning; they can "frozen" and then activated later ("thawed"), like a flare. Only one such frozen effect may be stored up at a time; if you summon a Being with a frozen effect and already have one in storage, you must discard one of them. 6f5237df18c320ad589bff69fa437f5d2751025c 1905 1904 2016-07-15T19:52:07Z Nandblock 11082 /* DEATHMATCH RULES: TWO-PLAYERS (DUEL) */ wikitext text/x-wiki == HIGH FORM RULES == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === The starting player takes a turn consisting of a single action. In subsequent turns, each player takes two of the following actions per turn: * - Place a common piece on an empty square * - Summon a being * - Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its victory points (VPs) if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. === Game End and Scoring === When one player scores 9 VPs or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == DEATHMATCH RULES: TWO PLAYERS (DUEL) == No tasks are used. The first player to score 18 VPs triggers the endgame. Destroying pieces scores VPs as follows: * - 1 VP for every 2 common pieces, rounded down * - 1 VP for a heroic piece * - 2 VPs for a legendary piece Summoning a legend scores 1 VP. (The VP is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 VP. == DEATHMATCH RULES: THREE OR FOUR PLAYERS == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. === Improvised Summoning === Once per game, and once for each opponent's colour, a player may use an opponent's piece as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) Only one piece may be used per improvised summoning: you can't use two different opponent's pieces simultaneously). == EVERFROST EXPANSION == Several Beings in the Everfrost deck have "frozen effects". These are effects that do not have to take place immediately upon summoning; they can "frozen" and then activated later ("thawed"), like a flare. Only one such frozen effect may be stored up at a time; if you summon a Being with a frozen effect and already have one in storage, you must discard one of them. f0c892a441f586978fe3f0ba6238e3df92f8dd70 1906 1905 2016-07-15T20:13:21Z Nandblock 11082 /* EVERFROST EXPANSION */ wikitext text/x-wiki == HIGH FORM RULES == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are available, the fourth not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === The starting player takes a turn consisting of a single action. In subsequent turns, each player takes two of the following actions per turn: * - Place a common piece on an empty square * - Summon a being * - Discard a card In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its victory points (VPs) if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece given in the card’s top left via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, resolve the effects listed on its card. The patterns for Legendary Beings require one or more heroic piece. Each legendary piece on the board earns 1 VP. Each player can have a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of their decks. Once the turn is over they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. === Game End and Scoring === When one player scores 9 VPs or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. If their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == DEATHMATCH RULES: TWO PLAYERS (DUEL) == No tasks are used. The first player to score 18 VPs triggers the endgame. Destroying pieces scores VPs as follows: * - 1 VP for every 2 common pieces, rounded down * - 1 VP for a heroic piece * - 2 VPs for a legendary piece Summoning a legend scores 1 VP. (The VP is not lost if the piece is later destroyed.) If you play a flare your opponent gains 1 VP. == DEATHMATCH RULES: THREE OR FOUR PLAYERS == Scores are tracked separately in each colour. Your final score is the lowest score. (The second and if necessary/applicable third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) in a single colour. === Improvised Summoning === Once per game, and once for each opponent's colour, a player may use an opponent's piece as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) Only one piece may be used per improvised summoning: you can't use two different opponent's pieces simultaneously). == EVERFROST EXPANSION == Several Beings in the Everfrost deck have "frozen effects". These effects that do not have to take place immediately upon summoning; they can be "frozen" and activated later ("thawed"), like a flare. Only one such frozen effect may be stored at a time; if you summon a Being with a frozen effect and already have one in storage, you must discard frozen effect. be803417cbc48c92a22cbe1be9704cbb1fbfb8b2 1908 1906 2016-07-22T14:57:40Z Nandblock 11082 wikitext text/x-wiki == HIGH FORM RULES == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are immediately available; the fourth is not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === The starting player takes a single action. In subsequent turns, each player takes two of the following actions per turn: * - Place a common piece on any empty square * - Summon a being * - Discard a card and (optionally) return other cards to their decks In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its victory points (VPs) if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece in the top left corner, via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, the effects listed on its card are activated. Patterns for Legendary Beings require one or more heroic pieces. Each legendary piece on the board earns 1 VP. Each player can place a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of the appropriate decks. Once the turn is over, they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. (Heroic and common pieces come from the same pool--in the original boardgame, they are reverse sides of the same piece--but there are only three legendary pieces for each colour.) === Game End and Scoring === When one player scores 9 VPs or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. Even if their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of heroic pieces; (2) total number of pieces. == DEATHMATCH RULES: TWO PLAYERS (DUEL) == No tasks are used. Opening positions are marked on the game board. The first player to score 18 VPs triggers the endgame. Destroying pieces scores VPs as follows: * - 1 VP for every 2 common pieces, rounded down * - 1 VP for a heroic piece * - 2 VPs for a legendary piece Summoning a legend scores 1 VP. This VP is not lost if the piece is later destroyed. If you play a flare your opponent gains 1 VP. == DEATHMATCH RULES: THREE OR FOUR PLAYERS == Scores are tracked separately in each colour. Your final score is the lowest of these scores. (The second and, in 4-player games, third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) VPs in a single colour. === Improvised Summoning === Once per game, and once for each opponent's colour, a player may use an opponent's piece as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) Only one piece may be used per improvised summoning: you may not use two different opponent's pieces simultaneously. == EVERFROST EXPANSION == Several Beings in the Everfrost deck have "frozen effects". These effects do not have to take place immediately upon summoning; they can be activated later ("thawed"), like a flare. Only one such frozen effect may be stored at a time; if you summon a Being with a frozen effect and already have one in storage, you must discard one or the other frozen effect. a1802423c0a5b0baee4b616aac36ccf138928a77 1931 1908 2016-08-07T19:56:51Z Cactus tom 8011 /* Game End and Scoring */ wikitext text/x-wiki == HIGH FORM RULES == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are immediately available; the fourth is not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === The starting player takes a single action. In subsequent turns, each player takes two of the following actions per turn: * - Place a common piece on any empty square * - Summon a being * - Discard a card and (optionally) return other cards to their decks In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its victory points (VPs) if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece in the top left corner, via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, the effects listed on its card are activated. Patterns for Legendary Beings require one or more heroic pieces. Each legendary piece on the board earns 1 VP. Each player can place a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of the appropriate decks. Once the turn is over, they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. (Heroic and common pieces come from the same pool--in the original boardgame, they are reverse sides of the same piece--but there are only three legendary pieces for each colour.) === Game End and Scoring === When one player scores 9 VPs or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. Even if their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of upgraded (i.e. heroic and legendary) pieces; (2) total number of pieces. == DEATHMATCH RULES: TWO PLAYERS (DUEL) == No tasks are used. Opening positions are marked on the game board. The first player to score 18 VPs triggers the endgame. Destroying pieces scores VPs as follows: * - 1 VP for every 2 common pieces, rounded down * - 1 VP for a heroic piece * - 2 VPs for a legendary piece Summoning a legend scores 1 VP. This VP is not lost if the piece is later destroyed. If you play a flare your opponent gains 1 VP. == DEATHMATCH RULES: THREE OR FOUR PLAYERS == Scores are tracked separately in each colour. Your final score is the lowest of these scores. (The second and, in 4-player games, third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) VPs in a single colour. === Improvised Summoning === Once per game, and once for each opponent's colour, a player may use an opponent's piece as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) Only one piece may be used per improvised summoning: you may not use two different opponent's pieces simultaneously. == EVERFROST EXPANSION == Several Beings in the Everfrost deck have "frozen effects". These effects do not have to take place immediately upon summoning; they can be activated later ("thawed"), like a flare. Only one such frozen effect may be stored at a time; if you summon a Being with a frozen effect and already have one in storage, you must discard one or the other frozen effect. c654b02acf1ddacd3cc748a962afcd8f4032495f 1934 1931 2016-08-08T23:38:55Z Nandblock 11082 /* Terminology */ wikitext text/x-wiki == HIGH FORM RULES == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece by one step. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are immediately available; the fourth is not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === The starting player takes a single action. In subsequent turns, each player takes two of the following actions per turn: * - Place a common piece on any empty square * - Summon a being * - Discard a card and (optionally) return other cards to their decks In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its victory points (VPs) if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece in the top left corner, via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, the effects listed on its card are activated. Patterns for Legendary Beings require one or more heroic pieces. Each legendary piece on the board earns 1 VP. Each player can place a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of the appropriate decks. Once the turn is over, they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. (Heroic and common pieces come from the same pool--in the original boardgame, they are reverse sides of the same piece--but there are only three legendary pieces for each colour.) === Game End and Scoring === When one player scores 9 VPs or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. Even if their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of upgraded (i.e. heroic and legendary) pieces; (2) total number of pieces. == DEATHMATCH RULES: TWO PLAYERS (DUEL) == No tasks are used. Opening positions are marked on the game board. The first player to score 18 VPs triggers the endgame. Destroying pieces scores VPs as follows: * - 1 VP for every 2 common pieces, rounded down * - 1 VP for a heroic piece * - 2 VPs for a legendary piece Summoning a legend scores 1 VP. This VP is not lost if the piece is later destroyed. If you play a flare your opponent gains 1 VP. == DEATHMATCH RULES: THREE OR FOUR PLAYERS == Scores are tracked separately in each colour. Your final score is the lowest of these scores. (The second and, in 4-player games, third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) VPs in a single colour. === Improvised Summoning === Once per game, and once for each opponent's colour, a player may use an opponent's piece as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) Only one piece may be used per improvised summoning: you may not use two different opponent's pieces simultaneously. == EVERFROST EXPANSION == Several Beings in the Everfrost deck have "frozen effects". These effects do not have to take place immediately upon summoning; they can be activated later ("thawed"), like a flare. Only one such frozen effect may be stored at a time; if you summon a Being with a frozen effect and already have one in storage, you must discard one or the other frozen effect. 0fe1e577f200b574ab5998f25d94ab28096d4e1f 1935 1934 2016-08-08T23:41:16Z Nandblock 11082 /* Turns */ wikitext text/x-wiki == HIGH FORM RULES == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece by one step. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are immediately available; the fourth is not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === The starting player takes a single action. In subsequent turns, each player takes two actions. These may be any of the following: * - Place a common piece on any empty square * - Summon a being * - Discard a card and (optionally) return other cards to their decks In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its victory points (VPs) if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece in the top left corner, via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, the effects listed on its card are activated. Patterns for Legendary Beings require one or more heroic pieces. Each legendary piece on the board earns 1 VP. Each player can place a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of the appropriate decks. Once the turn is over, they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. (Heroic and common pieces come from the same pool--in the original boardgame, they are reverse sides of the same piece--but there are only three legendary pieces for each colour.) === Game End and Scoring === When one player scores 9 VPs or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. Even if their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of upgraded (i.e. heroic and legendary) pieces; (2) total number of pieces. == DEATHMATCH RULES: TWO PLAYERS (DUEL) == No tasks are used. Opening positions are marked on the game board. The first player to score 18 VPs triggers the endgame. Destroying pieces scores VPs as follows: * - 1 VP for every 2 common pieces, rounded down * - 1 VP for a heroic piece * - 2 VPs for a legendary piece Summoning a legend scores 1 VP. This VP is not lost if the piece is later destroyed. If you play a flare your opponent gains 1 VP. == DEATHMATCH RULES: THREE OR FOUR PLAYERS == Scores are tracked separately in each colour. Your final score is the lowest of these scores. (The second and, in 4-player games, third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) VPs in a single colour. === Improvised Summoning === Once per game, and once for each opponent's colour, a player may use an opponent's piece as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) Only one piece may be used per improvised summoning: you may not use two different opponent's pieces simultaneously. == EVERFROST EXPANSION == Several Beings in the Everfrost deck have "frozen effects". These effects do not have to take place immediately upon summoning; they can be activated later ("thawed"), like a flare. Only one such frozen effect may be stored at a time; if you summon a Being with a frozen effect and already have one in storage, you must discard one or the other frozen effect. 148a9bd90617fd86489262d038c743abd57c5bb5 1936 1935 2016-08-08T23:42:48Z Nandblock 11082 /* Turns */ wikitext text/x-wiki == HIGH FORM RULES == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece by one step. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are immediately available; the fourth is not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === The starting player takes a single action. In subsequent turns, each player takes two actions. These may be any of the following: * - Place a common piece on any empty square * - Summon a being * - Discard a card and (optionally) return other cards to their decks. ''(Only permitted once per turn.)'' In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its victory points (VPs) if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece in the top left corner, via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, the effects listed on its card are activated. Patterns for Legendary Beings require one or more heroic pieces. Each legendary piece on the board earns 1 VP. Each player can place a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of the appropriate decks. Once the turn is over, they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. (Heroic and common pieces come from the same pool--in the original boardgame, they are reverse sides of the same piece--but there are only three legendary pieces for each colour.) === Game End and Scoring === When one player scores 9 VPs or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. Even if their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of upgraded (i.e. heroic and legendary) pieces; (2) total number of pieces. == DEATHMATCH RULES: TWO PLAYERS (DUEL) == No tasks are used. Opening positions are marked on the game board. The first player to score 18 VPs triggers the endgame. Destroying pieces scores VPs as follows: * - 1 VP for every 2 common pieces, rounded down * - 1 VP for a heroic piece * - 2 VPs for a legendary piece Summoning a legend scores 1 VP. This VP is not lost if the piece is later destroyed. If you play a flare your opponent gains 1 VP. == DEATHMATCH RULES: THREE OR FOUR PLAYERS == Scores are tracked separately in each colour. Your final score is the lowest of these scores. (The second and, in 4-player games, third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) VPs in a single colour. === Improvised Summoning === Once per game, and once for each opponent's colour, a player may use an opponent's piece as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) Only one piece may be used per improvised summoning: you may not use two different opponent's pieces simultaneously. == EVERFROST EXPANSION == Several Beings in the Everfrost deck have "frozen effects". These effects do not have to take place immediately upon summoning; they can be activated later ("thawed"), like a flare. Only one such frozen effect may be stored at a time; if you summon a Being with a frozen effect and already have one in storage, you must discard one or the other frozen effect. d893c7a45cf34b8a05569c370fb879c83e0e29d3 1937 1936 2016-08-08T23:44:55Z Nandblock 11082 /* Game End and Scoring */ wikitext text/x-wiki == HIGH FORM RULES == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece by one step. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are immediately available; the fourth is not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === The starting player takes a single action. In subsequent turns, each player takes two actions. These may be any of the following: * - Place a common piece on any empty square * - Summon a being * - Discard a card and (optionally) return other cards to their decks. ''(Only permitted once per turn.)'' In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its victory points (VPs) if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece in the top left corner, via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, the effects listed on its card are activated. Patterns for Legendary Beings require one or more heroic pieces. Each legendary piece on the board earns 1 VP. Each player can place a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of the appropriate decks. Once the turn is over, they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. (Heroic and common pieces come from the same pool--in the original boardgame, they are reverse sides of the same piece--but there are only three legendary pieces for each colour.) === Game End and Scoring === When one player scores 9 VPs or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. Even if their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of upgraded pieces; (2) total number of pieces. == DEATHMATCH RULES: TWO PLAYERS (DUEL) == No tasks are used. Opening positions are marked on the game board. The first player to score 18 VPs triggers the endgame. Destroying pieces scores VPs as follows: * - 1 VP for every 2 common pieces, rounded down * - 1 VP for a heroic piece * - 2 VPs for a legendary piece Summoning a legend scores 1 VP. This VP is not lost if the piece is later destroyed. If you play a flare your opponent gains 1 VP. == DEATHMATCH RULES: THREE OR FOUR PLAYERS == Scores are tracked separately in each colour. Your final score is the lowest of these scores. (The second and, in 4-player games, third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) VPs in a single colour. === Improvised Summoning === Once per game, and once for each opponent's colour, a player may use an opponent's piece as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) Only one piece may be used per improvised summoning: you may not use two different opponent's pieces simultaneously. == EVERFROST EXPANSION == Several Beings in the Everfrost deck have "frozen effects". These effects do not have to take place immediately upon summoning; they can be activated later ("thawed"), like a flare. Only one such frozen effect may be stored at a time; if you summon a Being with a frozen effect and already have one in storage, you must discard one or the other frozen effect. 20f349cd7ad4809dc74944f7dd65b70b64c87581 1938 1937 2016-08-09T00:02:04Z Nandblock 11082 /* DEATHMATCH RULES: THREE OR FOUR PLAYERS */ wikitext text/x-wiki == HIGH FORM RULES == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece by one step. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are immediately available; the fourth is not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === The starting player takes a single action. In subsequent turns, each player takes two actions. These may be any of the following: * - Place a common piece on any empty square * - Summon a being * - Discard a card and (optionally) return other cards to their decks. ''(Only permitted once per turn.)'' In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its victory points (VPs) if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece in the top left corner, via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, the effects listed on its card are activated. Patterns for Legendary Beings require one or more heroic pieces. Each legendary piece on the board earns 1 VP. Each player can place a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of the appropriate decks. Once the turn is over, they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. (Heroic and common pieces come from the same pool--in the original boardgame, they are reverse sides of the same piece--but there are only three legendary pieces for each colour.) === Game End and Scoring === When one player scores 9 VPs or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. Even if their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of upgraded pieces; (2) total number of pieces. == DEATHMATCH RULES: TWO PLAYERS (DUEL) == No tasks are used. Opening positions are marked on the game board. The first player to score 18 VPs triggers the endgame. Destroying pieces scores VPs as follows: * - 1 VP for every 2 common pieces, rounded down * - 1 VP for a heroic piece * - 2 VPs for a legendary piece Summoning a legend scores 1 VP. This VP is not lost if the piece is later destroyed. If you play a flare your opponent gains 1 VP. == DEATHMATCH RULES: THREE OR FOUR PLAYERS == Setup: In three-player Deathmatch, the third player places one common piece adjacent to each diamond symbol. In four-player Deathmatch, the fourth player places one common piece adjacent to each diamond symbol for the first, third and fourth players. As usual, the first player only gets one action. (Sounds complicated? Don't worry, BGA automates the setup.) Scores are tracked separately in each colour. Your final score is the lowest of these scores. (The second and, in 4-player games, third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) VPs in a single colour. === Improvised Summoning === Once per game, and once for each opponent's colour, a player may use an opponent's piece as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) Only one piece may be used per improvised summoning: you may not use two different opponent's pieces simultaneously. == EVERFROST EXPANSION == Several Beings in the Everfrost deck have "frozen effects". These effects do not have to take place immediately upon summoning; they can be activated later ("thawed"), like a flare. Only one such frozen effect may be stored at a time; if you summon a Being with a frozen effect and already have one in storage, you must discard one or the other frozen effect. f88a100445a6c5d5faccee3afea19f891b2fac4d 1939 1938 2016-08-12T12:31:06Z Nandblock 11082 /* Improvised Summoning */ wikitext text/x-wiki == HIGH FORM RULES == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece by one step. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of the same or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are immediately available; the fourth is not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === The starting player takes a single action. In subsequent turns, each player takes two actions. These may be any of the following: * - Place a common piece on any empty square * - Summon a being * - Discard a card and (optionally) return other cards to their decks. ''(Only permitted once per turn.)'' In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its victory points (VPs) if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece in the top left corner, via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, the effects listed on its card are activated. Patterns for Legendary Beings require one or more heroic pieces. Each legendary piece on the board earns 1 VP. Each player can place a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of the appropriate decks. Once the turn is over, they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. (Heroic and common pieces come from the same pool--in the original boardgame, they are reverse sides of the same piece--but there are only three legendary pieces for each colour.) === Game End and Scoring === When one player scores 9 VPs or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. Even if their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of upgraded pieces; (2) total number of pieces. == DEATHMATCH RULES: TWO PLAYERS (DUEL) == No tasks are used. Opening positions are marked on the game board. The first player to score 18 VPs triggers the endgame. Destroying pieces scores VPs as follows: * - 1 VP for every 2 common pieces, rounded down * - 1 VP for a heroic piece * - 2 VPs for a legendary piece Summoning a legend scores 1 VP. This VP is not lost if the piece is later destroyed. If you play a flare your opponent gains 1 VP. == DEATHMATCH RULES: THREE OR FOUR PLAYERS == Setup: In three-player Deathmatch, the third player places one common piece adjacent to each diamond symbol. In four-player Deathmatch, the fourth player places one common piece adjacent to each diamond symbol for the first, third and fourth players. As usual, the first player only gets one action. (Sounds complicated? Don't worry, BGA automates the setup.) Scores are tracked separately in each colour. Your final score is the lowest of these scores. (The second and, in 4-player games, third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) VPs in a single colour. === Improvised Summoning === Once per game, and once for each opponent's colour, a player may use an opponent's piece as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) Only one piece may be used per improvised summoning: you may not use two different opponents' pieces simultaneously. == EVERFROST EXPANSION == Several Beings in the Everfrost deck have "frozen effects". These effects do not have to take place immediately upon summoning; they can be activated later ("thawed"), like a flare. Only one such frozen effect may be stored at a time; if you summon a Being with a frozen effect and already have one in storage, you must discard one or the other frozen effect. 015a91ff2f746619f6ab212b7006dc4e65fafc65 1948 1939 2016-09-02T00:04:26Z Nandblock 11082 /* Terminology */ wikitext text/x-wiki == HIGH FORM RULES == High form is currently only implemented as a two-player game on BGA. === Terminology === Pieces are ranked in order: '''common, heroic, legendary.''' '''Upgrade''' and '''downgrade''' mean changing the rank of a piece by one step. A higher ranked piece may count (for summoning or tasks) as if it were of lower rank. A '''move''' is one square in any direction (including diagonals). A '''leap''' is from any square to any other. A '''standard move/leap''' is permitted onto any empty square or one occupied by a piece of a lesser rank. A '''combat move/leap''' is permitted onto any empty square or one occupied by a piece of ''the same'' or lesser rank. Any piece previously occupying the destination square of a move/leap is destroyed. You may destroy your own pieces. === Setup === Each player receives 3 cards from their personal deck, plus 2 Legendary Beings and one flare from the common decks. Four cards are drawn for the task queue. The first three are immediately available; the fourth is not yet available. Three tasks of the same type may not be active at once (BGA automatically enforces this rule). === Turns === The starting player takes a single action. In subsequent turns, each player takes two actions. These may be any of the following: * - Place a common piece on any empty square * - Summon a being * - Discard a card and (optionally) return other cards to their decks. ''(Only permitted once per turn.)'' In addition, before or after any action, a flare may be played, if one or both of its conditions are met. Once a turn is over: * - You may claim one task card and earn its victory points (VPs) if you meet its conditions. * - If necessary, replenish your hand from the appropriate decks and update the task queue. (Automated on BGA.) === Playing a Flare === Each flare lists two numbers: X/Y. The top effect may be activated if a player has X fewer upgraded pieces on the board than their opponent; the bottom effect if they have Y fewer pieces in total on the board. Effects activate in top-to-bottom order. === Summoning === If your pieces are in the formation on a Being’s card (in any orientation or mirror image), you may summon the piece in the top left corner, via a combat leap onto the white square in the pattern. For most beings, the white square is empty, but some require a piece of your own to be present in the square. Once the Being is summoned, the effects listed on its card are activated. Patterns for Legendary Beings require one or more heroic pieces. Each legendary piece on the board earns 1 VP. Each player can place a maximum of 3 legendary pieces on the board. If one is destroyed, 1 VP is lost. === Discarding === Once per turn a player may discard a card. They may also return as many other cards as they like (regular cards, legends, flares) to the bottom of the appropriate decks. Once the turn is over, they replenish their hand as usual. === Running Out of Pieces === If a player needs to place a piece and has no more in stock, they must pick up one from the board before placing the new piece. (Heroic and common pieces come from the same pool--in the original boardgame, they are reverse sides of the same piece--but there are only three legendary pieces for each colour.) === Game End and Scoring === When one player scores 9 VPs or draws the last card from their own deck, game end is triggered. Everyone plays one more turn, including the player who triggered endgame. Even if their score decreases below 9 due to destruction of a legendary piece, the game still ends. High score wins. Tiebreakers are, in order, (1) number of upgraded pieces; (2) total number of pieces. == DEATHMATCH RULES: TWO PLAYERS (DUEL) == No tasks are used. Opening positions are marked on the game board. The first player to score 18 VPs triggers the endgame. Destroying pieces scores VPs as follows: * - 1 VP for every 2 common pieces, rounded down * - 1 VP for a heroic piece * - 2 VPs for a legendary piece Summoning a legend scores 1 VP. This VP is not lost if the piece is later destroyed. If you play a flare your opponent gains 1 VP. == DEATHMATCH RULES: THREE OR FOUR PLAYERS == Setup: In three-player Deathmatch, the third player places one common piece adjacent to each diamond symbol. In four-player Deathmatch, the fourth player places one common piece adjacent to each diamond symbol for the first, third and fourth players. As usual, the first player only gets one action. (Sounds complicated? Don't worry, BGA automates the setup.) Scores are tracked separately in each colour. Your final score is the lowest of these scores. (The second and, in 4-player games, third lowest scores are used as tiebreakers.) When you score common pieces, first all common colour pairs are scored; then, if two common pieces of different colours remain, you may choose which colour to score against. When you summon a legend, you may choose which opponent to score 1 VP against. You may meet one or both criteria for a flare against multiple opponents, in which case you may choose whom to trigger it against (and give them 1 VP). Endgame is triggered by a player scoring 12 (for three-player) or 10 (for four-player) VPs in a single colour. === Improvised Summoning === Once per game, and once for each opponent's colour, a player may use an opponent's piece as their own when summoning a Being. (Thus in a 3-player game, a player may perform two improvised summonings; in a 4-player game, three--one for each opponent's colour.) Only one piece may be used per improvised summoning: you may not use two different opponents' pieces simultaneously. == EVERFROST EXPANSION == Several Beings in the Everfrost deck have "frozen effects". These effects do not have to take place immediately upon summoning; they can be activated later ("thawed"), like a flare. Only one such frozen effect may be stored at a time; if you summon a Being with a frozen effect and already have one in storage, you must discard one or the other frozen effect. 9850928b80cce6f7a39a7120ca953034f496db98 Gamehelpsaboteur 0 32 1907 1796 2016-07-17T04:29:26Z 333-blue 13923 wikitext text/x-wiki ==1== === Goal === Get as many gold nuggets as possible during the three rounds of the game. In order to do so, # if you are a '''gold digger''', you must, in association with other gold diggers, build a path from the 'Start' card to the treasure card which can be found among the three 'End' cards # if you are a '''saboteur''', you must, in association with other saboteurs, prevent the gold diggers to get to the treasure. Your role (gold digger or saboteur) will be randomly selected at the start of each round. === Rules summary === On your turn, you must click on a card from your hand to select it, then play this card or discard it. You can also rotate a 'Path' card before playing it by clicking the 'rotate' arrow that appears above the card. The cards are of several types: * 'Path' card: you can play this card to extend the maze, provided it is compatible with the cards already in place. To do this, click the location where you want to put the card. * 'Sabotage' card: you can break another player's tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score). A player with a broken tool cannot play a Path card. * 'Repair' card: you can repair your, or another player's, broken tool of the type indicated. To do this, click the corresponding tool in the target player's panel (under the score), or click on the 'Sabotage' card in front of you. * 'Map' card: you can play this card on any 'End' card to discover whether or not the treasure lies there (you alone will get the information, other players will see nothing). Just click on the 'End' card that you want to know. Then click on "I have seen it" button at the top. * 'Rock fall' card: this card lets you remove any 'Path' card of the maze. Just click on the card you want to remove. === Cards in play === * 44 'Path' cards * 9 'Sabotage' cards (three for each tool) * 6 'Repair a tool' cards (two for each tool) * 3 'Repair a tool among these two' cards (one for each combination of two tools) * 5 'Map' cards (one less than in the box set, as requested by the game author) * 3 'Rock fall' cards * 28 'Gold' cards ** 16 with one gold nugget ** 8 with two gold nuggets ** 4 with three gold nuggets === Roles === Roles are randomly selected among a set that depends upon the number of players: * with 3 players: 1 saboteur and 3 gold diggers * with 4 players: 1 saboteur and 4 gold diggers * with 5 players: 2 saboteurs and 4 gold diggers * with 6 players: 2 saboteurs and 5 gold diggers * with 7 players: 3 saboteurs and 5 gold diggers * with 8 players: 3 saboteurs and 6 gold diggers * with 9 players: 3 saboteurs and 7 gold diggers * with 10 players: 4 saboteurs and 7 gold diggers === Available variants === The game author, '''Frederic Moyersoen''', told us about some game variants, and we implemented all four of them. Please tell us which one is your favourite in the forum! Two variants are about gold sharing: *'''Old Mine:''' the old mine was not as packed with gold... sometimes all you got for your digging was worthless stones. In this variant, some 'Gold' cards do not yield any gold nuggets (among the 28 'Gold' cards, 4 are worth three nuggets, 8 are worth two nuggets, 10 are worth one nugget and 6 are worthless). So it is definitely best to get first to the treasure in order to be sure not to leave empty-handed! *'''New mine:''' the new mine is more even to each gold digger. Instead of distributing as many 'Gold' cards as the number of players - which benefits most to the gold digger that gets first to the treasure as he often gets two 'Gold' cards - it distributes as many 'Gold' cards as the number of gold diggers in play. Therefore, each gold digger will get only one 'Gold' card (however, it is still best to be first go get to the treasure in order to get a card of higher value!) Two variants are about gameplay: *'''Competitive:''' the gold diggers who have a 'Sabotage' card (broken pickaxe, lamp or trolley) laid in front of them at the end of a round, do not receive a 'Gold' card when their team wins the round. The 'Gold' cards are distributed between the gold diggers who have no broken tool (saboteurs are not affected by this rule). Therefore, with this variant it can be interesting to sabotage some of your fellow gold diggers... but not too often, so as not to make your team lose! *'''Selfish dwarf:''' one of the gold diggers will get a red jacket. This gold digger is a selfish dwarf: he can only win if he manages to complete the connection to the treasure himself. In this case, he gets four gold nuggets while the other players get nothing at all. If another gold digger completes the connection, the selfish dwarf takes no part in the treasure sharing (which is done with as many 'Gold' cards as the number of players, selfish dwarf excluded) '''Have a good game !''' ==2== 8aa7933c925c40d8845fdc4f585dc6296807543e Game statistics: stats.inc.php 0 95 1909 1595 2016-07-23T02:14:36Z Victoria la 11989 wikitext text/x-wiki In this file, you are describing game statistics, that will be displayed at the end of the game. After modifying this file, you must use "Reload statistics configuration" in BGA Studio Control Panel -> Manage Games ("Game Configuration" section): http://en.studio.boardgamearena.com/#!studio There are 2 types of statistics: * table statistics, that are not associated to a specific player (i.e.: one value for each game). * player statistics, that are associated to each players (i.e.: one value for each player in the game). Statistics types can be "int" for integer, "float" for floating point values, and "bool" for boolean. Once you defined your statistics there, you can start using "initStat", "setStat" and "incStat" method in your game logic, using statistics names defined below. !! It is not a good idea to modify this file when a game is running !! If your game is already public on BGA, please read the following before any change: http://en.doc.boardgamearena.com/Post-release_phase#Changes_that_breaks_the_games_in_progress Notes: * Statistic index is the reference used in setStat/incStat/initStat PHP method * Statistic index must contains alphanumerical characters and no space. Example: 'turn_played' * Statistics IDs must be >=10 * Two table statistics can't share the same ID, two player statistics can't share the same ID * A table statistic can have the same ID than a player statistics * Statistics ID is the reference used by BGA website. If you change the ID, you lost all historical statistic data. Do NOT re-use an ID of a deleted statistic * Statistic name is the English description of the statistic as shown to players <pre> $stats_type = array( // Statistics global to table "table" => array( "turns_number" => array("id"=> 10, "name" => totranslate("Number of turns"), "type" => "int" ), ), // Statistics existing for each player "player" => array( "turns_number" => array("id"=> 10, "name" => totranslate("Number of turns"), "type" => "int" ), "player_teststat1" => array( "id"=> 11, "name" => totranslate("player test stat 1"), "type" => "int" ), "player_teststat2" => array( "id"=> 12, "name" => totranslate("player test stat 2"), "type" => "float" ) ) ); </pre> c2af3099ad7aebe01086d3ca195fa323a83e358e 1910 1909 2016-07-23T02:17:46Z Victoria la 11989 wikitext text/x-wiki In this file, you are describing game statistics, that will be displayed at the end of the game. After modifying this file, you must use "Reload statistics configuration" in BGA Studio Control Panel -> Manage Games ("Game Configuration" section): http://en.studio.boardgamearena.com/#!studio There are 2 types of statistics: * table statistics, that are not associated to a specific player (i.e.: one value for each game). * player statistics, that are associated to each players (i.e.: one value for each player in the game). Statistics types can be "int" for integer, "float" for floating point values, and "bool" for boolean. Once you defined your statistics there, you can start using "initStat", "setStat" and "incStat" methods in your game logic, using statistics names defined below. See API http://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Game_statistics. !! It is not a good idea to modify this file when a game is running !! If your game is already public on BGA, please read the following before any change: http://en.doc.boardgamearena.com/Post-release_phase#Changes_that_breaks_the_games_in_progress Notes: * Statistic index is the reference used in setStat/incStat/initStat PHP method * Statistic index must contains alphanumerical characters and no space. Example: 'turn_played' * Statistics IDs must be >=10 * Two table statistics can't share the same ID, two player statistics can't share the same ID * A table statistic can have the same ID than a player statistics * Statistics ID is the reference used by BGA website. If you change the ID, you lost all historical statistic data. Do NOT re-use an ID of a deleted statistic * Statistic name is the English description of the statistic as shown to players <pre> $stats_type = array( // Statistics global to table "table" => array( "turns_number" => array("id"=> 10, "name" => totranslate("Number of turns"), "type" => "int" ), ), // Statistics existing for each player "player" => array( "turns_number" => array("id"=> 10, "name" => totranslate("Number of turns"), "type" => "int" ), "player_teststat1" => array( "id"=> 11, "name" => totranslate("player test stat 1"), "type" => "int" ), "player_teststat2" => array( "id"=> 12, "name" => totranslate("player test stat 2"), "type" => "float" ) ) ); </pre> 9d2cf386664633d95d6d585227742f2c6c12070b Main game logic: yourgamename.game.php 0 86 1911 1873 2016-07-23T02:21:10Z Victoria la 11989 /* Game statistics */ wikitext text/x-wiki This file is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. == File Structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * EmptyGame (constructor): where you define global variables. * setupNewGame: initial setup of the game. * getAllDatas: where you retrieve all game data during a complete reload of the game. * getGameProgression: where you compute the game progression indicator. * Utility functions: your utility functions. * Player actions: the entry points for players actions. * Game state arguments: methods to return additional data on specific game states ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#args more info here]). * Game state actions: the logic to run when entering a new game state ([http://en.doc.boardgamearena.com/Your_game_state_machine:_states.inc.php#action more info here]). * zombieTurn: what to do it's the turn of a zombie player. == Accessing player informations == ; getPlayersNumber() : Returns the number of players playing at the table : Note: doesn't work in setupNewGame so use count($players) instead ; getActivePlayerId() : Get the "active_player", whatever what is the current state type. : Note: it does NOT mean that this player is active right now, because state type could be "game" or "multiplayer" : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; getActivePlayerName() : Get the "active_player" name : Note: avoid using this method in a "multiplayer" state because it does not mean anything. ; loadPlayersBasicInfos() : Get an associative array with generic data about players (ie: not game specific data). : The key of the associative array is the player id. : The content of each value is: : * player_name : * player_color (ex: ff0000) ; getCurrentPlayerId() : Get the "current_player". The current player is the one from which the action originated (the one who send the request). : '''Be careful''': It is not always the active player. : In general, you shouldn't use this method, unless you are in "multiplayer" state. ; getCurrentPlayerName() : Get the "current_player" name : Be careful using this method (see above). ; getCurrentPlayerColor() : Get the "current_player" color : Be careful using this method (see above). ; isCurrentPlayerZombie() : Check the "current_player" zombie status. If true, player leave the game. == Accessing database == The main game logic should be the only point from where you should access to the game database. You access your database using SQL queries with the methods below. '''IMPORTANT''' BGA is using [http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html database transactions]. It means that your database changes WON'T BE APPLIED to the database until your request ends normally. Using transaction is in fact very useful for you: at any time, if your game logic detects that something is wrong (ex: unallowed move), you just have to throw an exception and all the changes already performed on the game situation will be removed. ; DbQuery( $sql ) : This is the generic method to access the database. : It can execute any type of SELECT/UPDATE/DELETE/REPLACE query on the database. : You should use it for UPDATE/DELETE/REPLACE query. For SELECT queries, the specialized methods below are much better. ; getUniqueValueFromDB( $sql ) : Returns a unique value from DB or null if no value is found. : $sql must be a SELECT query. : Raise an exception if more than 1 row is returned. ; getCollectionFromDB( $sql, $bSingleValue=false ) : Returns an associative array of rows for a sql SELECT query. : The key of the resulting associative array is the first field specified in the SELECT query. : The value of the resulting associative array if an associative array with all the field specified in the SELECT query and associated values. : First column must be a primary or alternate key. : The resulting collection can be empty. : If you specified $bSingleValue=true and if your SQL query request 2 fields A and B, the method returns an associative array "A=>B" Example 1: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( 1234 => array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), 1235 => array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getCollectionFromDB( "SELECT player_id id, player_name name FROM player", true ); Result: array( 1234 => 'myuser0', 1235 => 'myuser1' ) </pre> ; getNonEmptyCollectionFromDB( $sql ) : Idem than previous one, but raise an exception if the collection is empty ; getObjectFromDB( $sql ) : Returns one row for the sql SELECT query as an associative array or null if there is no result : Raise an exception if the query return more than one row Example: <pre> self::getObjectFromDB( "SELECT player_id id, player_name name, player_score score FROM player WHERE player_id='$player_id'" ); Result: array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ) </pre> ; getNonEmptyObjectFromDB( $sql ) : Idem than previous one, but raise an exception if no row is found ; getObjectListFromDB( $sql, $bUniqueValue=false ) : Return an array of rows for a sql SELECT query. : the result if the same than "getCollectionFromDB" except that the result is a simple array (and not an associative array). : The result can be empty. : If you specified $bUniqueValue=true and if your SQL query request 1 field, the method returns directly an array of values. Example 1: <pre> self::getObjectListFromDB( "SELECT player_id id, player_name name, player_score score FROM player" ); Result: array( array( 'id'=>1234, 'name'=>'myuser0', 'score'=>1 ), array( 'id'=>1235, 'name'=>'myuser1', 'score'=>0 ) ) </pre> Example 2: <pre> self::getObjectListFromDB( "SELECT player_name name FROM player", true ); Result: array( 'myuser0', 'myuser1' ) </pre> ; getDoubleKeyCollectionFromDB( $sql, $bSingleValue=false ) : Return an associative array of associative array, from a SQL SELECT query. : First array level correspond to first column specified in SQL query. : Second array level correspond to second column specified in SQL query. : If bSingleValue = true, keep only third column on result ; DbGetLastId() : Return the PRIMARY key of the last inserted row (see PHP mysql_insert_id function). ; DbAffectedRow() : Return the number of row affected by the last operation ; escapeStringForDB( $string ) : You must use this function on every string type data in your database that contains unsafe data. : (unsafe = can be modified by a player). : This method makes sure that no SQL injection will be done through the string used. : Note: if you using standard types in ajax actions, like AT_alphanum it is sanitized before arrival, : this is only needed if you manage to get unchecked string, like in the games where user has to enter text as a response. <pre> </pre> Note: see Editing [[Game database model: dbmodel.sql]] to know how to define your database model. == Use globals == Sometimes, you have to keep a single integer value that is global to your game, and you don't want to create a DB table specifically for it. Using a BGA framework "global", you can do such a thing. Your value will be stored in the "global" table in database, and you can access it with simple methods. '''initGameStateLabels''' This method is located at the beginning of your game logic. This is the place you defines the globals used in your game logic, by assigning them IDs. You can define up to 79 globals, with IDs from 10 to 89. You must NOT use globals outside this range as globals are used by other components of the framework. <pre> self::initGameStateLabels( array( "my_first_global_variable" => 10, "my_second_global_variable" => 11 ) ); </pre> '''setGameStateInitialValue( $value_label, $value_value )''' Init your global value. Must be called before any use of your global, so you should call this method from your "setupNewGame" method. '''getGameStateValue( $value_label )''' Retrieve the current value of a global. '''setGameStateValue( $value_label, $value_value )''' Set the current value of a global. '''incGameStateValue( $value_label, $increment )''' Increment the current value of a global. If increment is negative, decrement the value of the global. Return the final value of the global. == Game states and active players == ; checkAction( $actionName, $bThrowException=true ) : Check if action is valid regarding current game state (exception if fails). : The action is valid if it is listed as a "possibleactions" in the current game state (see game state description). : This method MUST be called in the first place in ALL your PHP methods that handle players action, in order to make sure a player can't do an action when the rules disallow it at this moment of the game. : if "bThrowException" is set to "false", the function return false in case of failure instead of throwing and exception. This is useful when several actions are possible in order to test each of them without throwing exceptions. ; activeNextPlayer() : Make the next player active in the natural player order. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; activePrevPlayer() : Make the previous player active (in the natural player order). : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->changeActivePlayer( $player_id ) : You can call this method to make any player active. : Note: you CANT use this method in a "activeplayer" or "multipleactiveplayer" state. You must use a "game" type game state for this. ; $this->gamestate->getActivePlayerList() : With this method you can retrieve the list of the active player at any time. : During a "game" type gamestate, it will return a void array. : During a "activeplayer" type gamestate, it will return an array with one value (the active player id). : during a "multipleactiveplayer" type gamestate, it will return an array of the active players id. : Note: you should only use this method is the latter case. ; $this->gamestate->setAllPlayersMultiactive() : With this method, all playing players are made active. : Usually, you use this method at the beginning (ex: "st" action method) of a multiplayer game state when all players have to do some action. ; $this->gamestate->setPlayersMultiactive( $players, $next_state ) : Make a specific list of players active during a multiactive gamestate. : Bare in mind it doesn't deactivate other previously active players. : "players" is the array of player id that should be made active. : In case "players" is empty, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->setPlayerNonMultiactive( $player_id, $next_state ) : During a multiactive game state, make the specified player inactive. : Usually, you call this method during a multiactive game state after a player did his action. : If this player was the last active player, the method trigger the "next_state" transition to go to the next game state. ; $this->gamestate->checkPossibleAction( $action ) : (rarely used) : This works exactly like "checkAction", except that it do NOT check if current player is active. : This is used specifically in certain game states when you want to authorize some additional actions for players that are not active at the moment. : Example: in Libertalia game, you want to authorize players to change their mind about card played. They are of course not active at the time they change their mind, so you cannot use "checkAction" and use "checkPossibleAction" instead. ; $this->gamestate->nextState( $transition ) : Change current state to a new state. Important: parameter $transition is the name of the transition, and NOT the name of the target game state, see [[Your game state machine: states.inc.php]] for more information about states. ; $this->gamestate->state() : Get an associative array of current game state attributes, see [[Your game state machine: states.inc.php]] for state attributes. $state=$this->gamestate->state(); if( $state['name'] == 'myGameState' ) {...} == Players turn order == '''getNextPlayerTable()''' Return an associative array which associate each player with the next player around the table. In addition, key 0 is associated to the first player to play. Example: if three player with ID 1, 2 and 3 are around the table, in this order, the method returns: <pre> array( 1 => 2, 2 => 3, 3 => 1, 0 => 1 ); </pre> '''getPrevPlayerTable()''' Same as above, but the associative array associate the previous player around the table. '''getPlayerAfter( $player_id )''' Get player playing after given player in natural playing order. '''getPlayerBefore( $player_id )''' Get player playing before given player in natural playing order. == Notify players == To understand notifications, please read [http://www.slideshare.net/boardgamearena/the-bga-framework-at-a-glance The BGA Framework at a glance] first. '''IMPORTANT''' Notifications are sent at the very end of the request, when it ends normally. It means that if you throw an exception for any reason (ex: move not allowed), no notifications will be sent to players. Notifications sent between the game start (setupNewGame) and the end of the "action" method of the first active state will never reach their destination. '''notifyAllPlayers( $notification_type, $notification_log, $notification_args )''' Send a notification to all players of the game. * notification_type: A string that defines the type of your notification. Your game interface Javascript logic will use this to know what is the type of the received notification (and to trigger the corresponding method). * notification_log: A string that defines what is to be displayed in the game log. You can use an empty string here (""). In this case, nothing is displayed in the game log. If you define a real string here, you should use "clienttranslate" method to make sure it can be translate. You can use arguments in your notification_log strings, that refers to values defines in the "notification_args" argument (see below). NB: Make sure you only use single quotes ('), otherwise PHP will try to interpolate the variable and will ignore the values in the args array. Note: you CAN use some HTML inside your notification log, and it is working. However: _ pay attention to keep the log clear. _ try to not include some HTML tags inside the "clienttranslate" method, otherwise it will make the translators work more difficult. You can use a notification argument instead, and provide your HTML through this argument. * notification_args: The arguments of your notifications, as an associative array. This array will be transmitted to the game interface logic, in order the game interface can be updated. Complete notifyAllPlayers example (from "Reversi"): <pre> self::notifyAllPlayers( "playDisc", clienttranslate( '${player_name} plays a disc and turns over ${returned_nbr} disc(s)' ), array( 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'returned_nbr' => count( $turnedOverDiscs ), 'x' => $x, 'y' => $y ) ); </pre> You can see in the example above the use of the "clienttranslate" method, and the use of 2 arguments "player_name" and "returned_nbr" in the notification log. Important: NO private data must be sent with this method, as a cheater could see it even it is not used explicitly by the game interface logic. If you want to send private information to a player, please use notifyPlayer below. '''notifyPlayer( $player_id, $notification_type, $notification_log, $notification_args )''' Same as above, except that the notification is sent to one player only. This method must be used each time some private information must be transmitted to a player. Important: the variable for player name must be ${player_name} in order to be highlighted with the player color in the game log == Game statistics == There are 2 types of statistics: * a "player" statistic is a statistic associated to a player * a "table" statistics is a statistic not associated to a player (global statistic for this game). See [[Game statistics: stats.inc.php]] to see how you defines statistics for your game. '''initStat( $table_or_player, $name, $value, $player_id=null )''' Create a statistic entry for the specified statistics with a default value. This method must be called for each statistics of your game, in your setupNewGame method. '$table_or_player' must be set to "table" if this is a table statistics, or "player" if this is a player statistics. '$name' is the name of your statistics, as it has been defined in your stats.inc.php file. '$value' is the initial value of the statistics. If this is a player statistics and if the player is not specified by "$player_id" argument, the value is set for ALL players. '''setStat( $value, $name, $player_id = null )''' Set a statistic $name to $value. If "$player_id" is not specified, setStat consider it is a TABLE statistic. If "$player_id" is specified, setStat consider it is a PLAYER statistic. '''incStat( $delta, $name, $player_id = null )''' Increment (or decrement) specified statistic value by $delta value. Same behavior as setStat function. == Translations == See [[Translations]] == Manage player scores and Tie breaker == At the end of the game, players automatically get a rank depending on their score: the player with the biggest score is #1, the player with the second biggest score is #2, and so on... During the game, you update player's score directly by updating "player_score" field of "player" table in database. Examples: <pre> // +2 points to active player self::DbQuery( "UPDATE player SET player_score=player_score+2 WHERE player_id='".self::getActivePlayerId()."'" ); // Set score of active player to 5 self::DbQuery( "UPDATE player SET player_score=5 WHERE player_id='".self::getActivePlayerId()."'" ); </pre> Note: don't forget to notify the client side in order the score control can be updated accordingly. '''Tie breaker''' Tie breaker is used when two players get the same score at the end of a game. Tie breaker is using "player_score_aux" field of "player" table. It is updated exactly like the "player_score" field. Tie breaker score is displayed only for players who are tied at the end of the game. Most of the time, it is not supposed to be displayed explicitly during the game. When you are using "player_score_aux" functionality, you must describe the formula to use in your gameinfos.inc.php file like this: <pre> 'tie_breaker_description' => totranslate("Describe here your tie breaker formula"), </pre> This description will be used as a tooltip to explain to players how this auxiliary score has been calculated. == Reflexion time == ; function giveExtraTime( $player_id, $specific_time=null ) : Give standard extra time to this player. : Standard extra time depends on the speed of the game (small with "slow" game option, bigger with other options). : You can also specify an exact time to add, in seconds, with the "specified_time" argument (rarely used). == Managing errors and exceptions == Note: when you throw an exception, all database changes and all notifications are cancelled immediately. This way, the game situation that were existing before the request is completely restored. ; throw new BgaUserException ( $error_message) : Base class to notify a user error : You must throw this exception when a player want to do something that he is not allowed to do. : The error message will be shown to the player as a "red message", so it must be translated. : Throwing such an exception is NOT considered as a bug, so it is not traced in BGA error logs. Example from Gomoku: <pre> throw new BgaUserException( self::_("There is already a stone on this intersection, you can't play there") ); </pre> ; throw new BgaVisibleSystemException ( $error_message) : You must throw this exception when you detect something that is not supposed to happened into your code. : The error message is shown to the user as an "Unexpected error", in order he can report it in the forum. : The error message is logged in BGA error logs. If it happens regularly, we will report it to you. ; throw new BgaSystemException ( $error_message) : Base class to notify a system exception. The message will be hidden from the user, but show in the logs. Use this if the message contains technical information. : You shouldn't use this type of exception except if you think the information shown could be critical. Indeed: a generic error message will be shown to the user, so it's going to be difficult for you to see what happened. == Zombie mode == When a player leaves a game for any reason (expelled, quit), he becomes a "zombie player". In this case, the results of the game won't count for statistics, but this is cool if the other players can finish the game anyway. That's why zombie mode exists: allow the other player to finish the game, even if the situation is not ideal. While developing your zombie mode, keep in mind that: * Do not refer to the rules, because this situation is not planned by the rules. * Try to figure that you are playing with your friends and one of them has to leave: how can we finish the game without killing the spirit of the game? * The idea is NOT to develop an artificial intelligence for the game. Most of the time, the best thing to do when it is zombie player turn is to jump immediately to a state where he is not active anymore. For example, if he is in a game state where he has a choice between playing A and playing B, the best thing to do is NOT to choose A or B, but to pass. So, even if there's no "pass" action in the rules, add a "zombiepass" transitition in your game state and use it. Each time a zombie player must play, your "zombieTurn" method is called. Parameters: * $state: the name of the current game state. * $active_player: the id of the active player. Most of the time, your zombieTurn method looks like this: <pre> function zombieTurn( $state, $active_player ) { $statename = $state['name']; if( $statename == 'myFirstGameState' || $statename == 'my2ndGameState' || $statename == 'my3rdGameState' .... ) { $this->gamestate->nextState( "zombiePass" ); } else throw new BgaVisibleSystemException( "Zombie mode not supported at this game state: ".$statename ); } </pre> Note that in the example above, all corresponding game state should implement "zombiePass" as a transition. == Player elimination == In some games, this is useful to eliminate a player from the game in order he/she can start another game without waiting for the current game end. This case should be rare. Please don't use player elimination feature if some player just has to wait the last 10% of the game for game end. This feature should be used only in games where players are eliminated all along the game (typical examples: "Perudo" or "The Werewolves of Miller's Hollow"). Usage: * Player to eliminate should NOT be active anymore (preferably use the feature in a "game" type game state). * In your PHP code: self::eliminatePlayer( <player_to_eliminate_id> ); * the player is informed in a dialog box that he no longer have to played and can start another game if he/she wants too (whith buttons "stay at this table" "quit table and back to main site"). In any case, the player is free to tart&join another table from now. * When your game is over, all players who have been eliminated before receive a "notification" (the small "!" icon on the top right of the BGA interface) that indicate them that "the game has ended" and invite them to review the game results. == Player color preferences == BGA players (Club members) may now choose their preferred color for playing. For example, if they are used to play green for every board game, they can select "green" in their BGA preferences page. Making your game compatible with colors preferences is very easy and requires only 1 line of PHP and 1 configuration change : On your gameinfos.inc.php file, add the following lines : // Favorite colors support : if set to "true", support attribution of favorite colors based on player's preferences (see reattributeColorsBasedOnPreferences PHP method) 'favorite_colors_support' => true, Then, on your main <your_game>.game.php file, find the "reloadPlayersBasicInfos" call in your "setupNewGame" method and replace : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reloadPlayersBasicInfos(); By : $sql .= implode( $values, ',' ); self::DbQuery( $sql ); self::reattributeColorsBasedOnPreferences( $players, array( /* LIST HERE THE AVAILABLE COLORS OF YOUR GAME INSTEAD OF THESE ONES */"ff0000", "008000", "0000ff", "ffa500", "773300" ) ); self::reloadPlayersBasicInfos(); The "reattributeColorsBasedOnPreferences" method reattributes all colors, taking into account players color preferences and available colors. Note that you must update the colors to indicate the colors available for your game. 2 important remarks : * for some games (ex : Chess), the color has an influence on a mechanism of the game, most of the time by giving a special advantage to a player (ex : Starting the game). Color preference mechanism must NOT be used in such a case. * your logic should NEVER consider that the first player has the color X, that the second player has the color Y, and so on. If this is the case, your game will NOT be compatible with reattributeColorsBasedOnPreferences as this method attribute colors to players based on their preferences and not based as their order at the table. Colours currently listed as a choice in preferences: * #ff0000 Red * #008000 Green * #0000ff Blue * #ffa500 Yellow * #000000 Black * #ffffff White == Debugging and Tracing == To debug php code you can use some tracing functions available from the parent class such as debug, trace, error, warn, dump. self::debug("Ahh!"); self::dump('my_var',$my_var); See [[Practical_debugging]] section for complete information about debugging interfaces and where to find logs. d0747bd3a0fac00affe48e6adbbcc1fb87bb5315 Game interface logic: yourgamename.js 0 88 1912 1668 2016-07-26T02:02:32Z Victoria la 11989 /* Confirmation dialog */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; this.isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> The third parameter of dojo.place can take various interesting value. values possibles : "replace" : (see description above). "first" : Places the node as a child of the reference node. The node is placed as the first child. "last" : Places the node as a child of the reference node. The node is placed as the last child. "before" : places the node right before the reference node. "last (value by default) " : places the node right after the reference node. "only" : replaces all children of the reference node with the node. positif integer : This parameter can be a positif integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. See also full doc on dojo.place : [http://dojotoolkit.org/reference-guide/1.7/dojo/place.] Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight, (opt)color )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight (optional): if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. * color: could be '''blue''' (default), '''red''' or '''gray'''. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''this.addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips '''this.removeTooltip( nodeId )''' Remove a tooltip from the DOM node. == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Multiple choice dialog === You can use this dialog to give user a choice with small amount of options: <pre> var keys = [1,5,10]; this.multipleChoiceDialog( _('How many bugs to fix?"), keys, dojo.hitch(this, function(choice) { var bugchoice = keys[choice]; console.log('dialog callback with '+bugchoice); this.ajaxcall( '/mygame/mygame/fixBugs.html', { bugs: bugchoice}, this, function( result ) {} ); })); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: <pre> // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]: var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); </pre> Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a "<div id='myDlgContent'>" div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> You can also use three extra attributes in the parameter array for the notification: <pre> $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table, "header" => '<div>Some header</div>', "footer" => '<div>Some footer</div>', "closelabel" => clienttranslate( "Closing button label" ) ) ); </pre> *'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors) *'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names) *'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update. == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Gomoku example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. '''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> b31dcb705d8f5e133abd8a6ea69ea6c7829aba8f 1913 1912 2016-07-26T02:09:48Z Victoria la 11989 /* Dialogs */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; this.isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> The third parameter of dojo.place can take various interesting value. values possibles : "replace" : (see description above). "first" : Places the node as a child of the reference node. The node is placed as the first child. "last" : Places the node as a child of the reference node. The node is placed as the last child. "before" : places the node right before the reference node. "last (value by default) " : places the node right after the reference node. "only" : replaces all children of the reference node with the node. positif integer : This parameter can be a positif integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. See also full doc on dojo.place : [http://dojotoolkit.org/reference-guide/1.7/dojo/place.] Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same than "slideToObjectPos", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight, (opt)color )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight (optional): if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. * color: could be '''blue''' (default), '''red''' or '''gray'''. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''this.addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips '''this.removeTooltip( nodeId )''' Remove a tooltip from the DOM node. == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Multiple choice dialog === You can use this dialog to give user a choice with small amount of options: <pre> var keys = [1,5,10]; this.multipleChoiceDialog( _('How many bugs to fix?"), keys, dojo.hitch(this, function(choice) { var bugchoice = keys[choice]; console.log('dialog callback with '+bugchoice); this.ajaxcall( '/mygame/mygame/fixBugs.html', { bugs: bugchoice}, this, function( result ) {} ); })); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]] var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a <nowiki><div id='myDlgContent'></nowiki> div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> You can also use three extra attributes in the parameter array for the notification: <pre> $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table, "header" => '<div>Some header</div>', "footer" => '<div>Some footer</div>', "closelabel" => clienttranslate( "Closing button label" ) ) ); </pre> *'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors) *'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names) *'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update. == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Gomoku example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. '''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 2893a9562c7e41c0e7e528706d9abb1f497f2815 1946 1913 2016-08-31T01:59:47Z Victoria la 11989 /* Animations */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; this.isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> The third parameter of dojo.place can take various interesting value. values possibles : "replace" : (see description above). "first" : Places the node as a child of the reference node. The node is placed as the first child. "last" : Places the node as a child of the reference node. The node is placed as the last child. "before" : places the node right before the reference node. "last (value by default) " : places the node right after the reference node. "only" : replaces all children of the reference node with the node. positif integer : This parameter can be a positif integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. See also full doc on dojo.place : [http://dojotoolkit.org/reference-guide/1.7/dojo/place.] Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same as "slideToObject", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight, (opt)color )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight (optional): if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. * color: could be '''blue''' (default), '''red''' or '''gray'''. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''this.addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips '''this.removeTooltip( nodeId )''' Remove a tooltip from the DOM node. == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Multiple choice dialog === You can use this dialog to give user a choice with small amount of options: <pre> var keys = [1,5,10]; this.multipleChoiceDialog( _('How many bugs to fix?"), keys, dojo.hitch(this, function(choice) { var bugchoice = keys[choice]; console.log('dialog callback with '+bugchoice); this.ajaxcall( '/mygame/mygame/fixBugs.html', { bugs: bugchoice}, this, function( result ) {} ); })); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]] var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a <nowiki><div id='myDlgContent'></nowiki> div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> You can also use three extra attributes in the parameter array for the notification: <pre> $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table, "header" => '<div>Some header</div>', "footer" => '<div>Some footer</div>', "closelabel" => clienttranslate( "Closing button label" ) ) ); </pre> *'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors) *'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names) *'''closelabel''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). NB: this last parameter is not yet - 24/02/2014 - deployed on the studio, but can be used already and will take effect immediately with the next update. == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Gomoku example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. '''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 9c73ed776bc1a231b2f5ac8bb297f084375cdf2a Gamehelpthejellymonsterlab 0 141 1914 1477 2016-07-27T01:52:58Z 333-blue 13923 wikitext text/x-wiki In The Jelly Monster Lab you are a scientist trying to make the best jelly monsters. In order to do it so, you need to move through the labs, trying to find the parts you need to make your monsters. At the beginning, every player starts with two experiments. Every experiment shows a monster made with a colored body (blue, red, pink or green), eyes (1, 2 or 3) and a mouth (happy or sad) and a lab where you must make it. The parts are spread out over the six labs, so you move to them, and grab the parts you need to make your monsters, but you cannot have more than 5 cards in your hand. To move cards to and from your hand, click on the card then click the arrows to the right of the "Your hand" section. Once you have your experiment card and the parts, move to the lab indicated by the experiment card and leave all there (the experiment card and the parts). When other player come to visit that lab, it'll find your monster and then, it will be yours. While you're moving through the labs, you're leaving trails in order to know which player has been the last visiting it. If you move to a lab with a trail, there may be a monster of the owner of the trail. In addition, you can't move to a lab you were the last visit, so you need to program your moves to have all the parts of the experiment before you arrive to the lab where you must leave it with all the parts in your hand. In any time, you may want to go to the center to pick up a new experiment and make new monsters. But you'll not be able to go to the center if you just came from there (your meeple shows laid down) and if you have the maximum cards in hand (five). When a player has 4 monsters done, the center is open to close the game. Any player who goes there, finishes the game. Every monster has an score on it, depending on how difficult is to find their parts. You can see how many parts are in the game of each type, and what are all the experiments in the guide card placed on the bottom left corner of the playboard. The player with the most score points win the game. Advice: If you have experiments, one side too low scored, or on the other side too difficult to find the parts, you can leave the experiment card in any lab, so other players can play with it, or maybe you can play with it in a later visit. *Sad: 8 cards (1 point) *1: 6 cards (1 point) *Blue: 4 cards (1 point) *Happy: 4 cards (2 points) *2: 4 cards (2 points) *Red: 3 cards (2 points) *Pink: 3 cards (2 points) *3: 2 cards (3 points) db38d2037342d1bb9ce52603d30385d7835b11d5 Gamehelpdudo 0 165 1915 1274 2016-07-27T01:54:43Z 333-blue 13923 moved [[Gamehelpdudo]] to [[Gamehelpperudo]] wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". A Paco counts as a wild card or joker - it can count as any other number. (On BGA, the Pacos are birds on the dice.) Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. '''This bid takes into account all of the dice on the table.''' He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos (ones), unless a player is Palifico (which will be explained later). After a bid is placed, the turn is passed on to the player on his left. This player has 2 options: 1. If he thinks that the last bid was wrong he can call "Dudo" (i doubt) 2. If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players reveal their dice. All dice that match the bid are counted, including Pacos.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> For example, let's say Bob calls "Dudo" on Abe's bid of four fives (four dice with the number five showing). When all the dice are revealed and counted up, there are 3 fives and 2 pacos. This counts as 5 fives, so Abe was safe with his bid. Bob loses a die for the rest of the game. '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. If Abe has called 6 fives instead of 3 in the same scenario, his bid is over the number of fives in play (only 5). If this is the case, Abe loses a die instead. The moment a player loses his last die, that player is out of the game. ====Option 2: increasing the bid==== If a player does not want to call Dudo, he has to make a higher bid of his own. To increase a bid a player has to choose one of the following options: 1. increase the number of dice, thus the value stays the same (ex. raising a bid of 2 threes with one of 3 threes) 2. increase the value on the die, thus the number of dice stays the same (ex. raising a bid of 2 threes with a bid of 2 fours or 2 sixes) 3. reset the value on the die by choosing Pacos. To do this, the number of Pacos bid has to be at least half the number of dice currently bid, rounded up. (ex. replacing a bid of 5 sixes with 3 Pacos) 4. raise the value from a Paco to another number. To do this, the number of dice bid needs to be at least double the number of Pacos plus one. (ex. replacing a bid of 3 Pacos with 7 threes) Changing the bid to Pacos is a way to make lower die values reachable again, at the expense of quickly raising the number of dice being bid. Once a new bid has been established the turn is passed on to the next player to the left, and play continues until someone calls Dudo. When Dudo has been called and a player loses a die, the player that lost his die starts a new round. If the player that lost a die is out, the player to the left of the eliminated player starts the next round instead. ===Palifico=== The moment a player has only one die remaining, this player has reached Palifico. This triggers a special round. During this round, Pacos no longer count as jokers, and an opening bid can be of Pacos. '''However''': during this round the value on the dice cannot be increased during bids. The value of the dice is locked in until someone calls Dudo. After this round, the game returns to normal, regardless of whether the Palifico player still has one die left. ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before another player places a new bid or calls Dudo. Anyone around the table (except the player who made the bid) is allowed to call out Calza. If the player that called out Calza was correct (the bid is exactly the same as the number of dice on the table) he regains one of his lost dice (if the player only had one die, then the next time they fall to having only one die will '''NOT''' trigger another Palifico round. One per player per game.). However, if he was wrong, he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice are still in the game, which helps to inform how high one can reasonably bid. </li></ol> bff0947c02c111c1ef41eb7f9b265024b57249da 1917 1915 2016-07-27T02:22:59Z 333-blue 13923 moved [[Gamehelpperudo]] to [[Gamehelpdudo]] over redirect wikitext text/x-wiki Attention!!, there are a lot of variations of Perudo. The variation implemented on BGA has been the Asmodée version. Unfortunately, for this version of the game there seems to be no online English rule book. The link on the game page links to another version of Perudo and consequently it discusses rules that are not implemented on this BGA version. ''Whenever we use '''he''' it can also be read as '''she''' '' ==Rules for Perudo (Asmodée version)== ===Goal of the Game=== Be the last remaining with at least 1 die in play. If you succeed in being the last player standing, no matter how many dice you have, you win! ===Set up=== Each player starts with 5 standard 6 sided dice, with numbers 1 through 6. A "1" is known as a "Paco". A Paco counts as a wild card or joker - it can count as any other number. (On BGA, the Pacos are birds on the dice.) Based on the number of players, the game begins with a different number of dice in play at the start: {| class="wikitable" |- ! No. Players ! No. Dice |- | 2 | 10 |- | 3 | 15 |- | 4 | 20 |- | 5 | 25 |- | 6 | 30 |} This is important to note at the start of a game, since you'll be making guesses based on all the dice on the table. ===Playing a Round=== All players roll their dice, and check to see what they rolled. The first player (randomly selected) starts with an opening bid; he calls a face value and a number of dice. '''This bid takes into account all of the dice on the table.''' He can either try to make a educated guess and try to be really close to the truth, based on his own hand, or he can try to bluff and lure other players into losing a die. '''Important:''' An opening bid can never begin with a bid of pacos (ones), unless a player is Palifico (which will be explained later). After a bid is placed, the turn is passed on to the player on his left. This player has 2 options: 1. If he thinks that the last bid was wrong he can call "Dudo" (i doubt) 2. If he thinks the last bid is reasonable, then he must increase the last bid. ====Option 1: calling Dudo==== As soon as Dudo is called all players reveal their dice. All dice that match the bid are counted, including Pacos.<br/> '''The bid is correct''' if the number of dice, with the correct value, is higher or exactly the same as the bid.<br/> In this case the player who called Dudo was wrong to have doubted and loses one die.<br/> For example, let's say Bob calls "Dudo" on Abe's bid of four fives (four dice with the number five showing). When all the dice are revealed and counted up, there are 3 fives and 2 pacos. This counts as 5 fives, so Abe was safe with his bid. Bob loses a die for the rest of the game. '''The bid is false''' when the number of dice, with the correct value, is lower then the bid.<br/> In this case the player who called Dudo was correct to doubt the bid and the player who placed the bid has to admit he was overstating things and loses one die. If Abe has called 6 fives instead of 3 in the same scenario, his bid is over the number of fives in play (only 5). If this is the case, Abe loses a die instead. The moment a player loses his last die, that player is out of the game. ====Option 2: increasing the bid==== If a player does not want to call Dudo, he has to make a higher bid of his own. To increase a bid a player has to choose one of the following options: 1. increase the number of dice, thus the value stays the same (ex. raising a bid of 2 threes with one of 3 threes) 2. increase the value on the die, thus the number of dice stays the same (ex. raising a bid of 2 threes with a bid of 2 fours or 2 sixes) 3. reset the value on the die by choosing Pacos. To do this, the number of Pacos bid has to be at least half the number of dice currently bid, rounded up. (ex. replacing a bid of 5 sixes with 3 Pacos) 4. raise the value from a Paco to another number. To do this, the number of dice bid needs to be at least double the number of Pacos plus one. (ex. replacing a bid of 3 Pacos with 7 threes) Changing the bid to Pacos is a way to make lower die values reachable again, at the expense of quickly raising the number of dice being bid. Once a new bid has been established the turn is passed on to the next player to the left, and play continues until someone calls Dudo. When Dudo has been called and a player loses a die, the player that lost his die starts a new round. If the player that lost a die is out, the player to the left of the eliminated player starts the next round instead. ===Palifico=== The moment a player has only one die remaining, this player has reached Palifico. This triggers a special round. During this round, Pacos no longer count as jokers, and an opening bid can be of Pacos. '''However''': during this round the value on the dice cannot be increased during bids. The value of the dice is locked in until someone calls Dudo. After this round, the game returns to normal, regardless of whether the Palifico player still has one die left. ===Optional rules=== <ol> <li>'''Calza!'''<br/> A player can call out a Calza (the bid is exact) before another player places a new bid or calls Dudo. Anyone around the table (except the player who made the bid) is allowed to call out Calza. If the player that called out Calza was correct (the bid is exactly the same as the number of dice on the table) he regains one of his lost dice (if the player only had one die, then the next time they fall to having only one die will '''NOT''' trigger another Palifico round. One per player per game.). However, if he was wrong, he loses a die. In either case the player who called out Calza will start the new round. </li> <li>'''The lost dice are visible'''<br/> When the lost dice are visible the game is slightly easier as you do not need to memorize how many dice are still in the game, which helps to inform how high one can reasonably bid. </li></ol> bff0947c02c111c1ef41eb7f9b265024b57249da Gamehelpperudo 0 224 1918 2016-07-27T02:22:59Z 333-blue 13923 moved [[Gamehelpperudo]] to [[Gamehelpdudo]] over redirect wikitext text/x-wiki #REDIRECT [[Gamehelpdudo]] 83b0e3e9df71159d95f6b70d78e912be8f21b55c Studio file reference 0 54 1919 1299 2016-07-29T00:32:02Z Victoria la 11989 /* 'img' directory */ wikitext text/x-wiki This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment. === 'img' directory === This directory contains the images for your game (the game art). See [[Game art: img directory]] === gameinfos.inc.php === In this file you describe the meta-information for your game: game name, publisher name, number of player, game categories, etc... === dbmodel.sql === File for creating specific database tables that you will need to persist data during the game (for example a table for cards). === gameoptions.inc.php === File for describing your game options (= game variants) === <gamename>.action.php === File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions. === <gamename>.css === CSS styles specific to your game. === <gamename>.game.php === This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. Also see [[Main_game_logic:_yourgamename.game.php|game.php]]. === <gamename>.js === This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. === <gamename>.view.php and <gamename>_<gamename>.tpl === Files used to set up the page layout ('view') for the game. === material.inc.php === File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants. === states.inc.php === This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). === stats.inc.php === File used to list statistics that you want to update during the game to be presented to players at the end of the game. === version.php === Don't edit this file. It is used internally by the build system. ecd0e3b51610906ca913bed917a984f23272e72d 1920 1919 2016-07-29T00:32:58Z Victoria la 11989 /* gameinfos.inc.php */ wikitext text/x-wiki This is a quick reference for the files used to implement a game. For more information, edit the file and read the introductory comment. === 'img' directory === This directory contains the images for your game (the game art). See [[Game art: img directory]] === gameinfos.inc.php === In this file you describe the meta-information for your game: game name, publisher name, number of player, game categories, etc... See [[Main game logic: yourgamename.game.php]]. === dbmodel.sql === File for creating specific database tables that you will need to persist data during the game (for example a table for cards). === gameoptions.inc.php === File for describing your game options (= game variants) === <gamename>.action.php === File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions. === <gamename>.css === CSS styles specific to your game. === <gamename>.game.php === This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. Also see [[Main_game_logic:_yourgamename.game.php|game.php]]. === <gamename>.js === This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. === <gamename>.view.php and <gamename>_<gamename>.tpl === Files used to set up the page layout ('view') for the game. === material.inc.php === File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants. === states.inc.php === This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). === stats.inc.php === File used to list statistics that you want to update during the game to be presented to players at the end of the game. === version.php === Don't edit this file. It is used internally by the build system. 0a6c4e1e5313f90407b4e876d167a971ef2d8849 1921 1920 2016-07-29T00:40:56Z Victoria la 11989 wikitext text/x-wiki This is a quick reference for the files used to implement a game. For more information, follow the wiki links. === img/ === This directory contains the images for your game (the game art). See [[Game art: img directory]] === gameinfos.inc.php === In this file you describe the meta-information for your game: game name, publisher name, number of player, game categories, etc... See [[Main game logic: yourgamename.game.php]]. === dbmodel.sql === File for creating specific database tables that you will need to persist data during the game (for example a table for cards). See [[Game database model: dbmodel.sql]] === gameoptions.inc.php === File for describing your game options (or game variants). See [[Game options and preferences: gameoptions.inc.php]]. === <gamename>.action.php === File used to describe methods that can be called from the client interface through javascript, get parameters and call the appropriate game functions. See [[Players actions: yourgamename.action.php]]. === <gamename>.css === CSS styles specific to your game. See [[Game interface stylesheet: yourgamename.css]]. === <gamename>.game.php === This is the main file for your game logic. Here you initialize the game, persist data, implement the rules and notify changes to the client interface. See [[Main game logic: yourgamename.game.php]]. === <gamename>.js === This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. See [[Game interface logic: yourgamename.js]]. === <gamename>.view.php and <gamename>_<gamename>.tpl === Files used to set up the page layout ('view') for the game. See [[Game layout: view and template: yourgamename.view.php and yourgamename yourgamename.tpl]]. === material.inc.php === File used to describe all the game material (cards with their description, dices, tokens...). You can also use it to define game constants. See [[Game material description: material.inc.php]]. === states.inc.php === This file describes the game states machine of your game (all the game states properties, and the transitions to get from one state to another). See [[Your game state machine: states.inc.php]]. === stats.inc.php === File used to list statistics that you want to update during the game to be presented to players at the end of the game. See [[Game statistics: stats.inc.php]]. === version.php === Don't edit this file. It is used internally by the build system. daaf00c47588c6f2e3ec3a9bc5a95aa9e8bddd1e Tools and tips of BGA Studio 0 99 1922 1854 2016-07-29T00:54:45Z Victoria la 11989 wikitext text/x-wiki == Server Tools and Tips == === Starting a game in one click === To start a game: * Create a new table with your game. * If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table. * Click on "Express Start". === Stopping a game in one click === * Click on the "quit" icon on the top right of the screen. * Click on "Express Stop". === Switching between users === When running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective. === Access to game database and Logs === At the bottom of the game area, there is section without a title containing 3 useful links: Go to game database • BGA request&SQL logs • BGA unexpected exceptions logs * "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game * BGA request&SQL logs - link to your studio PHP log - all tables, all severities. Anything you print using debugging and tracing functions from PHP and some framework logs * BGA unexpected exceptions logs - same log as above but only severity warning and higher See [Practical debugging] for more info about it. === Save & restore state === Using links of this section, you can save the complete current (database) state of your game, then restore it later. This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine. We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations. Limits: * the "restore" function does not work anymore when the game is over. * a saved situation from a given table cannot be restored in another table. * when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually. === Input/Output debugging section === This section shows you: * The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">" * The notifications received by your game interface. Notifications (inputs) begins with "<". Note: if you click on some notification title, you can resend it immediately to the user interface. === Run PHP functions from the chat === On BGA Studio, you can directly run a PHP method from the table chat. For example, if on your PHP you have this method: function giveMoneyToPlayer($player_id, $amount) { ... } You can call this method directly from the chat like this: giveMoneyToPlayer(2564,2) Note: this is not a real php statement, you cannot use self::, you cannot use ";" at the end and you cannot use quotes, if you need to pass a string skip the quotes, like this giveToActivePlayer(money,2) == Desktop/Client Tools and Tips == === Edit TPL (Template) File === To edit TPL with HTML code highlightings in Gedit under Ubuntu: find gtksourceview directory in /usr/share, depending on your version (2.0, 3.0,...). <br> Here it's 3.0, then type in a terminal window: <pre> sudo gedit /usr/share/gtksourceview-3.0/language-specs/html.lang </pre> then find 'globs' section, and change: <pre> <property name="globs">*.html;*.htm;*.tpl</property> </pre> 1491dbff361529314ac0027a2a5e86d00b3d1bad 1926 1922 2016-07-29T02:17:39Z Victoria la 11989 /* Desktop/Client Tools and Tips */ wikitext text/x-wiki == Server Tools and Tips == === Starting a game in one click === To start a game: * Create a new table with your game. * If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table. * Click on "Express Start". === Stopping a game in one click === * Click on the "quit" icon on the top right of the screen. * Click on "Express Stop". === Switching between users === When running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective. === Access to game database and Logs === At the bottom of the game area, there is section without a title containing 3 useful links: Go to game database • BGA request&SQL logs • BGA unexpected exceptions logs * "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game * BGA request&SQL logs - link to your studio PHP log - all tables, all severities. Anything you print using debugging and tracing functions from PHP and some framework logs * BGA unexpected exceptions logs - same log as above but only severity warning and higher See [Practical debugging] for more info about it. === Save & restore state === Using links of this section, you can save the complete current (database) state of your game, then restore it later. This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine. We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations. Limits: * the "restore" function does not work anymore when the game is over. * a saved situation from a given table cannot be restored in another table. * when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually. === Input/Output debugging section === This section shows you: * The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">" * The notifications received by your game interface. Notifications (inputs) begins with "<". Note: if you click on some notification title, you can resend it immediately to the user interface. === Run PHP functions from the chat === On BGA Studio, you can directly run a PHP method from the table chat. For example, if on your PHP you have this method: function giveMoneyToPlayer($player_id, $amount) { ... } You can call this method directly from the chat like this: giveMoneyToPlayer(2564,2) Note: this is not a real php statement, you cannot use self::, you cannot use ";" at the end and you cannot use quotes, if you need to pass a string skip the quotes, like this giveToActivePlayer(money,2) == Desktop/Client Tools and Tips == === Eclipse For PHP Developers === Eclipse PHP package can be starting point for development you need. You may also want to install Tern JS plugins to understand dojo style JS. All desktops. https://projects.eclipse.org/projects/tools.pdt === Visual Studio Code === Microsoft Visual Studio Code is light weight IDE/Editor. All desktops. https://code.visualstudio.com === Gedit (Ubuntu) === '''Edit TPL''' To edit TPL with HTML code highlightings in Gedit under Ubuntu: find gtksourceview directory in /usr/share, depending on your version (2.0, 3.0,...). <br> Here it's 3.0, then type in a terminal window: <pre> sudo gedit /usr/share/gtksourceview-3.0/language-specs/html.lang </pre> then find 'globs' section, and change: <pre> <property name="globs">*.html;*.htm;*.tpl</property> </pre> === File Sync on Windows === Install [http://winscp.net/ WinSCP]. Map a remote directory to a local one and enable continuous sync (one way). You need SFTP password you get when you registered dev account. === File Sync on Linux === * Option 1 - Nautilus (file manager) You can just use Nautilus "connect to a server" function with URL sftp://1.studio.boardgamearena.com Then you'll get a mounted local folder mapping your studio folder and you can use any editor you like without further need for sync. Downside - if connection goes down you cannot work on source code, no local copy. * Option 2 - sftp and rsync <pre> #!/bin/bash BASEDIR=`dirname $0` REMOTE=$BASEDIR/remote LOCAL=$BASEDIR/workspace GAME=mygamenamehere #mount remote fusermount -u $REMOTE #this unmounts dir echo LongDevPassword | sshfs -o password_stdin myusernamehere@1.studio.boardgamearena.com: $REMOTE #this starts auto-sync from local to remote mount killall lsyncd lsyncd -deplay 1 -rsync $LOCAL/$GAME/ $REMOTE/$GAME </pre> This can be able run on startup, so you don't have to do anything manually. However sshfs is not very stable you have to kill and restart it sometimes. And remote goes away sometimes due to connection issues with studio. In this case its handy to have a local copy. You can also sync on demand (from a build script or editor command) using rsync -vlrt $LOCAL/$GAME/ $REMOTE/$GAME === Version Control === Studio providers svn for you code on server, however there is no way to access history, restore or do anything with it unless you ask admins. If you want to keep your code in another repository. I suggest to use git with local repo, which you can sync to cloud or backup. === PHP CLI === Its handy to have php cli (command line) tools install to run php locally, so you can test some stuff without deployment cycle. === ImageMagick === Handy set of image manipulation command line tools, useful to for example to stitch together bunch of images and re-size, to use as sprite (in Stock component for example). I.e. you got a graphics file from publisher where every time is 600x600 PNG file with every time in separate file. You want .jpg instead of .png to make it not like 20Mb, all images in one column with size 128x128 /usr/bin/montage `ls Tiles*.png` -tile 1 -geometry 128x128+0+0 ../out/tiles128.jpg 23afa6afd65c9f9354600bfae697ae6a64be91b0 Practical debugging 0 100 1923 1300 2016-07-29T01:06:06Z Victoria la 11989 /* Some frequent errors */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" as per [[Studio logs]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> === Add traces to your code === You can use the following functions in your game to add server side logging: '''self::debug( $message );''' // debug level logging '''self::trace( $message );''' // info level logging '''self::warn( $message );''' // warning level logging '''self::error( $message );''' // error level logging To see the logs, you should check the "Current table error log" in the [[Studio_back-office|Studio backoffice]]. This can be useful when you need to follow the flow of your code and not just stop it to see how it goes at some point. Only the error log level will appear in production. This level should be used only for critical problems. Other levels will show only in the development environment and can be used as you see fit. == Debugging my HTML/CSS layout == Situation examples: * why my game element doesn't show up in the interface? * why my CSS property hasn't been applied to this element? * why this game element is displayed at this position? A first useful tip when an element does not show up in the interface is to give it a red background: <pre> #my_element { ... some CSS definitions ... background-color: red; } </pre> This way, you know if the element is not visible because of some of its CSS property or because of anything else. Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property. Using Chrome "Elements" tab (thre first one), you can: * See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code. * Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles. * You can even modify directly some CSS property and see if how it looks immediately on the game interface. == Debugging my Javascript game interface logic == Compare to PHP debugging, Javascript debugging can sometimes be painful. Here's are some tips to make your life easier while developing and debugging Javascript: === Do complex things on PHP side === PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first. The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property. Note: check Reversi example for this. === Add traces in your code === You can use the following: '''console.log( variable_to_inspect )''' It will give you the object structure of the variable in the Javascript console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. '''alert( variable_to_inspect )''' It will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. == Some frequent errors == See [[Troubleshooting]]. 4c5e2e2642858e580a5f41f508b3869ebadb55b4 Troubleshooting 0 220 1924 1881 2016-07-29T01:06:26Z Victoria la 11989 wikitext text/x-wiki Describing common errors which is hard to understand and debug == Game does not start at all == === Undefined offset: 0 in table/table.game.php on line 830 === You are likely calling self::getActivePlayerName () during setupNewGame() === Unexpected error: Wrong formatted data from BGA gameserver 1 (method: createGame): ... === This is generic message usually followed by exact position in your source code, and usually its syntax error in one of yours php script === Unexpected error: Propagating error from GS 1 (method: createGame): Fatal error during yourgame setup: Not logged === Calling self::getCurrentPlayerId () or using $g_user from 'args' state function, see also below === Fatal error during creation of database ebd_quoridor_389 Not logged === Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an 'args' function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. == Predefined server errors == === Unexpected error: Unexpected final game state (XX) === The action function does not transition to any state, i.e. selectField($field) { self::checkAction ( 'selectField' ); if ($field!=0) $this->gamestate->nextState ( 'next' ); } Here if $field is 0 there is no transition === This game action is impossible right now === Check the game log. Usually your state does not define the action you trying to perform in 'possibeactions' array. === Unexpected error: This transition (playerTurn) is impossible at this state (42) === This is pretty self explanatory. Function nextState() takes transition name not a state name, so you probably did not define this transition that the given state == Game interface hangs during reload or on start == Showing "Application Loading..." === Javascript error: During pageload undefined no_stack_avail Script: === This error usually has no useful data, but it means you called somes API that require a callback and did not define callback function, i.e in dojo.connect, this.connectClass, dojo.subscribe, etc this.connectClass('field', 'onclick', 'onField'); // <-- onField is not defined === Other errors with "Application loading..." === You probably have a syntax error in your Javascript code, and the interface refuses to load. To find this error, check if there is an error message in the Javascript console (F12). If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition. === Unexpected Syntax Error: === No further details in the log. When log is filling with some social connect errors. Possible Reason: Syntax error in of the php script which is loaded before the start, such as gameoptions.inc.php, gameinfos.inc.php and such. === Game interface spins in a loop throwing error === Errors is something like "Cannot read property 'is_ai' of undefined". Cannot restart the game because cannot access UI to stop. Likely you get in actplayer state with player id == 0. The only way to fix it is to edit database, globals index == 2 set player id to one of your test dudes (can copy from row 5 for example). == Other Errors == === When I do a move, I got "Move recorded, waiting for update ..." forever === "Move recorded" means that your ajaxcall request has been sent to the server and returned normally. "Waiting for update" means that your client interface is waiting for some notifications from the server that correspond to the move we just did. If this message stays forever, it is probably that your PHP code does not send any notification when the move happens, which is abnormal. To fix this: add a notifyAllPlayers or a notifyPlayer call in your PHP code. === Some player action is triggered randomly when I click somewhere on the game area === You probably used "dojo.connect" on a null object. In this case, dojo.connect associate the event (ex: "onclick") to the whole game area. Most of the time it happens in this situation, when my_object element does not exists: <pre> dojo.connect( $("my_object"), "onclick", this, function() { ... } </pre> To determine if this is the case, place "alert( $("my_object") )" before the dojo.connect to check if the object exists or not. === Javascript does not know how to sum two numbers === Be careful when you manipulate integers returned by notifications: most of the time, Javascript considers they are Strings and not Integers. As a result: <pre> var i=1; i += notif.args.increment; // With notif.args.increment='1' alert( i ); // i=11 instead of 2 !! Javascript concatenate 2 strings ! </pre> To solve this, you should use the "toint" function: <pre> var i=1; i += toint( notif.args.increment ); // With notif.args.increment='1' alert( i ); // i=2 :) </pre> === Javascript: do not use substr with negative numbers === To get the last characters of a string, use "slice" instead of "substr" which has a bug on IE: <pre> var three_last_characters = string.substr( -3 ); // Wrong var three_last_characters = string.slice( -3 ); // Correct </pre> 0ea3dd67db1656743db0a63d111edf6c642d344a 1925 1924 2016-07-29T01:13:05Z Victoria la 11989 wikitext text/x-wiki Describing common errors which is hard to understand and debug == Game does not start at all == === Undefined offset: 0 in table/table.game.php on line 830 === You are likely calling self::getActivePlayerName () during setupNewGame() === Unexpected error: Wrong formatted data from BGA gameserver 1 (method: createGame): ... === This is generic message usually followed by exact position in your source code, and usually its syntax error in one of yours php script === Unexpected error: Propagating error from GS 1 (method: createGame): Fatal error during yourgame setup: Not logged === Calling self::getCurrentPlayerId () or using $g_user from 'args' state function, see also below === Fatal error during creation of database ebd_quoridor_389 Not logged === Check that you didn't use $g_user or getCurrentPlayerId() in setupNewGame() function or in an 'args' function of your state. As these functions are not consequences of a user action, there is no current player defined. As a general rule, you should use getActivePlayerId() and not getCurrentPlayerId(). See the [http://www.slideshare.net/boardgamearena/bga-studio-focus-on-bga-game-state-machine presentation on the game state machine] for more information. == Predefined server errors == === Unexpected error: Unexpected final game state (XX) === The action function does not transition to any state, i.e. selectField($field) { self::checkAction ( 'selectField' ); if ($field!=0) $this->gamestate->nextState ( 'next' ); } Here if $field is 0 there is no transition === This game action is impossible right now === Check the game log. Usually your state does not define the action you trying to perform in 'possibeactions' array. === Unexpected error: This transition (playerTurn) is impossible at this state (42) === This is pretty self explanatory. Function nextState() takes transition name not a state name, so you probably did not define this transition that the given state == Game interface hangs during reload or on start == Showing "Application Loading..." === Javascript error: During pageload undefined no_stack_avail Script: === This error usually has no useful data, but it means you called somes API that require a callback and did not define callback function, i.e in dojo.connect, this.connectClass, dojo.subscribe, etc this.connectClass('field', 'onclick', 'onField'); // <-- onField is not defined === Other errors with "Application loading..." === You probably have a syntax error in your Javascript code, and the interface refuses to load. To find this error, check if there is an error message in the Javascript console (F12). If there is really nothing on the log, it's probably that the system was unable to load your Javascript because of an syntax error that affect the structure of the Javascript file, typically a missing "}" or a missing "," after a method definition. === Unexpected Syntax Error: === No further details in the log. When log is filling with some social connect errors. Possible Reason: Syntax error in of the php script which is loaded before the start, such as gameoptions.inc.php, gameinfos.inc.php and such. === Game interface spins in a loop throwing error === Errors is something like "Cannot read property 'is_ai' of undefined". Cannot restart the game because cannot access UI to stop. Likely you get in actplayer state with player id == 0. The only way to fix it is to edit database, globals index == 2 set player id to one of your test dudes (can copy from row 5 for example). == Other Errors == === When I do a move, I got "Move recorded, waiting for update ..." forever === "Move recorded" means that your ajaxcall request has been sent to the server and returned normally. "Waiting for update" means that your client interface is waiting for some notifications from the server that correspond to the move we just did. If this message stays forever, it is probably that your PHP code does not send any notification when the move happens, which is abnormal. To fix this: add a notifyAllPlayers or a notifyPlayer call in your PHP code. === When I do a move, I get "Sending move to server..." the nothing and game resets to state before the move === Its possible that server code get into infinite loops or thinks too much, in which case it will timeout and will be aborted without any extra logs (and any db transaction you saw in the log won't be committed). You will usually see "Unable to connect to server" message on console in this case. You have to put more logging into server to trace where it hangs. === Some player action is triggered randomly when I click somewhere on the game area === You probably used "dojo.connect" on a null object. In this case, dojo.connect associate the event (ex: "onclick") to the whole game area. Most of the time it happens in this situation, when my_object element does not exists: <pre> dojo.connect( $("my_object"), "onclick", this, function() { ... } </pre> To determine if this is the case, place "alert( $("my_object") )" before the dojo.connect to check if the object exists or not. === Javascript does not know how to sum two numbers === Be careful when you manipulate integers returned by notifications: most of the time, Javascript considers they are Strings and not Integers. As a result: <pre> var i=1; i += notif.args.increment; // With notif.args.increment='1' alert( i ); // i=11 instead of 2 !! Javascript concatenate 2 strings ! </pre> To solve this, you should use the "toint" function: <pre> var i=1; i += toint( notif.args.increment ); // With notif.args.increment='1' alert( i ); // i=2 :) </pre> === Javascript: do not use substr with negative numbers === To get the last characters of a string, use "slice" instead of "substr" which has a bug on IE: <pre> var three_last_characters = string.substr( -3 ); // Wrong var three_last_characters = string.slice( -3 ); // Correct </pre> bab3d1f5a57b12a4c2b46661708e97ee1c438387 Gamehelpk2 0 184 1927 1756 2016-08-02T14:51:07Z Kevinchan 14039 Add the card list. All players should know the card list before playing. wikitext text/x-wiki '''Turn Summary''' <ol> <li>'''Card Selection'''</li> <ol> <li>Each player plays 3 cards face down.</li> <li>Players reveal them simultaneously.</li> </ol> <li>'''Risk Tokens'''</li> <ol> <li>The player with the most movement points takes a risk token. In case of a tie, no one takes a risk token.</li> <li>Another risk token is revealed if needed.</li> </ol> <li>'''Action Phase'''</li> <ol> <li>Players move their climbers using their played (green) cards.</li> <li>Placing a tent costs the same as the cost to enter that space.</li> <li>Players increase their climbers' acclimatization level using their played (blue) cards.</li> <li>The player with a risk token must suffer the consequences and either reduce their movement by that amount or, if they choose not to, subtract acclimatization points from a climber who had one or more cards assigned to this turn.</li> <li>Each climber's newly gained victory points are marked on the victory point track.</li> <li>Note the influence of weather on movement (only in winter weather)!.</li> </ol> <li>'''Acclimatization Checks'''</li> <ol> <li>Add/subtract acclimatization according to each climber's current space.</li> <li>A tent of the player's color adds +1 to acclimatization.</li> <li>Subtract acclimatization resulting from the current weather, if in the affected altitude zone.</li> <li>If acclimatization exceeds 6, it is reduced back to 6.</li> <li>If acclimatization drops below 1, the climber dies, losing any VP gained.</li> </ol> <li>'''End of Turn'''</li> <ol> <li>The starting player marker passes to the left.</li> <li>The weather marker moves to the next space.</li> <li>Draw 3 cards to have 6 again.</li> </ol> </ol> '''Cardlist''' Total: 18 cards <ol> <li>Acclimatization cards (Blue)</li> {| class="wikitable" |- ! scope="row" style="width: 50pt; text-align: center;" | Points | style="width: 20pt; text-align: center;" | 3 | style="width: 20pt; text-align: center;" | 2 | style="width: 20pt; text-align: center;" | 1 | style="width: 20pt; text-align: center;" | 0 | style="width: 50pt; text-align: center;" | |- ! scope="row" | Quantity | style="text-align: center;" | 1 | style="text-align: center;" | 1 | style="text-align: center;" | 2 | style="text-align: center;" | 1 | style="text-align: center;" | Total: 5 |} <li>Movement cards (Green)</li> {| class="wikitable" |- ! scope="row" style="width: 50pt; text-align: center;" | Points | style="width: 20pt; text-align: center;" | 3 | style="width: 20pt; text-align: center;" | 2 | style="width: 20pt; text-align: center;" | 1 | style="width: 50pt; text-align: center;" | |- ! scope="row" | Quantity | style="text-align: center;" | 2 | style="text-align: center;" | 3 | style="text-align: center;" | 5 | style="text-align: center;" | Total: 10 |} <li>Rope cards (Green)</li> {| class="wikitable" |- ! scope="row" style="width: 50pt; text-align: center;" | Points | style="width: 20pt; text-align: center;" | 2|3 | style="width: 20pt; text-align: center;" | 1|3 | style="width: 20pt; text-align: center;" | 1|2 | style="width: 50pt; text-align: center;" | |- ! scope="row" | Quantity | style="text-align: center;" | 1 | style="text-align: center;" | 1 | style="text-align: center;" | 1 | style="text-align: center;" | Total: 3 |} </ol> 2ea62dce7b431e726790e2ef3d66aa4b365c2597 1928 1927 2016-08-02T14:52:34Z Kevinchan 14039 wikitext text/x-wiki '''Turn Summary''' <ol> <li>'''Card Selection'''</li> <ol> <li>Each player plays 3 cards face down.</li> <li>Players reveal them simultaneously.</li> </ol> <li>'''Risk Tokens'''</li> <ol> <li>The player with the most movement points takes a risk token. In case of a tie, no one takes a risk token.</li> <li>Another risk token is revealed if needed.</li> </ol> <li>'''Action Phase'''</li> <ol> <li>Players move their climbers using their played (green) cards.</li> <li>Placing a tent costs the same as the cost to enter that space.</li> <li>Players increase their climbers' acclimatization level using their played (blue) cards.</li> <li>The player with a risk token must suffer the consequences and either reduce their movement by that amount or, if they choose not to, subtract acclimatization points from a climber who had one or more cards assigned to this turn.</li> <li>Each climber's newly gained victory points are marked on the victory point track.</li> <li>Note the influence of weather on movement (only in winter weather)!.</li> </ol> <li>'''Acclimatization Checks'''</li> <ol> <li>Add/subtract acclimatization according to each climber's current space.</li> <li>A tent of the player's color adds +1 to acclimatization.</li> <li>Subtract acclimatization resulting from the current weather, if in the affected altitude zone.</li> <li>If acclimatization exceeds 6, it is reduced back to 6.</li> <li>If acclimatization drops below 1, the climber dies, losing any VP gained.</li> </ol> <li>'''End of Turn'''</li> <ol> <li>The starting player marker passes to the left.</li> <li>The weather marker moves to the next space.</li> <li>Draw 3 cards to have 6 again.</li> </ol> </ol> '''Cardlist''' Total: 18 cards <ol> <li>Acclimatization cards (Blue)</li> {| class="wikitable" style="border-spacing: 2px; border: 1px solid darkgray;" |- ! scope="row" style="width: 50pt; text-align: center;" | Points | style="width: 20pt; text-align: center;" | 3 | style="width: 20pt; text-align: center;" | 2 | style="width: 20pt; text-align: center;" | 1 | style="width: 20pt; text-align: center;" | 0 | style="width: 50pt; text-align: center;" | |- ! scope="row" | Quantity | style="text-align: center;" | 1 | style="text-align: center;" | 1 | style="text-align: center;" | 2 | style="text-align: center;" | 1 | style="text-align: center;" | Total: 5 |} <li>Movement cards (Green)</li> {| class="wikitable" style="border-spacing: 2px; border: 1px solid darkgray;" |- ! scope="row" style="width: 50pt; text-align: center;" | Points | style="width: 20pt; text-align: center;" | 3 | style="width: 20pt; text-align: center;" | 2 | style="width: 20pt; text-align: center;" | 1 | style="width: 50pt; text-align: center;" | |- ! scope="row" | Quantity | style="text-align: center;" | 2 | style="text-align: center;" | 3 | style="text-align: center;" | 5 | style="text-align: center;" | Total: 10 |} <li>Rope cards (Green)</li> {| class="wikitable" style="border-spacing: 2px; border: 1px solid darkgray;" |- ! scope="row" style="width: 50pt; text-align: center;" | Points | style="width: 20pt; text-align: center;" | 2|3 | style="width: 20pt; text-align: center;" | 1|3 | style="width: 20pt; text-align: center;" | 1|2 | style="width: 50pt; text-align: center;" | |- ! scope="row" | Quantity | style="text-align: center;" | 1 | style="text-align: center;" | 1 | style="text-align: center;" | 1 | style="text-align: center;" | Total: 3 |} </ol> d0ea0ab5b805b408501bab89a5aa2b98cf444cfa 1929 1928 2016-08-02T14:57:03Z Kevinchan 14039 wikitext text/x-wiki '''Turn Summary''' <ol> <li>'''Card Selection'''</li> <ol> <li>Each player plays 3 cards face down.</li> <li>Players reveal them simultaneously.</li> </ol> <li>'''Risk Tokens'''</li> <ol> <li>The player with the most movement points takes a risk token. In case of a tie, no one takes a risk token.</li> <li>Another risk token is revealed if needed.</li> </ol> <li>'''Action Phase'''</li> <ol> <li>Players move their climbers using their played (green) cards.</li> <li>Placing a tent costs the same as the cost to enter that space.</li> <li>Players increase their climbers' acclimatization level using their played (blue) cards.</li> <li>The player with a risk token must suffer the consequences and either reduce their movement by that amount or, if they choose not to, subtract acclimatization points from a climber who had one or more cards assigned to this turn.</li> <li>Each climber's newly gained victory points are marked on the victory point track.</li> <li>Note the influence of weather on movement (only in winter weather)!.</li> </ol> <li>'''Acclimatization Checks'''</li> <ol> <li>Add/subtract acclimatization according to each climber's current space.</li> <li>A tent of the player's color adds +1 to acclimatization.</li> <li>Subtract acclimatization resulting from the current weather, if in the affected altitude zone.</li> <li>If acclimatization exceeds 6, it is reduced back to 6.</li> <li>If acclimatization drops below 1, the climber dies, losing any VP gained.</li> </ol> <li>'''End of Turn'''</li> <ol> <li>The starting player marker passes to the left.</li> <li>The weather marker moves to the next space.</li> <li>Draw 3 cards to have 6 again.</li> </ol> </ol> '''Cardlist''' Total: 18 cards <ol> <li>Acclimatization cards (Blue)</li> {| class="wikitable" style="border-spacing: 2px; border: 1px solid darkgray;" |- ! scope="row" style="width: 50pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | Points | style="width: 20pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 3 | style="width: 20pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 2 | style="width: 20pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 1 | style="width: 20pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 0 | style="width: 50pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | |- ! scope="row" style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | Quantity | style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 1 | style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 1 | style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 2 | style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 1 | style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | Total: 5 |} <li>Movement cards (Green)</li> {| class="wikitable" style="border-spacing: 2px; border: 1px solid darkgray;" |- ! scope="row" style="width: 50pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | Points | style="width: 20pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 3 | style="width: 20pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 2 | style="width: 20pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 1 | style="width: 50pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | |- ! scope="row" style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | Quantity | style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 2 | style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 3 | style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 5 | style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | Total: 10 |} <li>Rope cards (Green)</li> {| class="wikitable" style="border-spacing: 2px; border: 1px solid darkgray;" |- ! scope="row" style="width: 50pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | Points | style="width: 20pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 2|3 | style="width: 20pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 1|3 | style="width: 20pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 1|2 | style="width: 50pt; text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | |- ! scope="row" style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | Quantity | style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 1 | style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 1 | style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | 1 | style="text-align: center; border-spacing: 2px; border: 1px solid darkgray;" | Total: 3 |} </ol> b7a8936cd328f7dc18282b6b39a4b99b59453e47 Translations 0 94 1930 1151 2016-08-03T01:53:48Z Victoria la 11989 /* On client side (Javascript) */ wikitext text/x-wiki Using BGA Studio, the game you create is ready to be translated to each language by the BGA community. To make this possible, you only need to specify which string must be translated and how to combine them. == How translation works? == When developing your game, all strings must be in English. Strings must be coherent with the English version of the game. Before the release of the game, BGA team will do the French translation of the game. After the release of the game, the BGA players community will translate the game in every language. == What should be translated? == Every text that can be visible by the player when the game is running normally. This includes tooltips, texts on cards, error messages, ... This does NOT include error messages that are not supposed to happened (unexpected errors). == Focus on translating notifications == Usually, translating a website is simple: you just call a function on every string you have to translate, and the string is translated in the player's language. On Board Game Arena, this is exactly the same with the "_( string )" function. However, there is one difference on BGA: notifications. The server is sending notifications to players, and most of the time the notifications are the same for every players, no matter what language each player is using. This is why notifications are translated on client side in the proper language, even if the strings are defined on server side. == WARNING: how to make sure your strings will be translated == For each game, our translation tool is doing a full scan of the code, looking for translator markers like "_()" or "clientranslate()"... (see below the list of translation markers). If your original string is not "physically" inside one of this marker, it won't be translated. <pre> // Examples: the following strings will be translated: var mystring_translated = _("my string"); // JS $mystring_translated = self::_("my string"); // PHP $mystring_translated = sprintf( _("my string with an %s argument"), $argument ); // PHP // Examples: the following strings WILL NOT be translated: $my_string = "my string"; $not_translated = self::_( $my_string ); // The original string is not bordered by a translator marker => no translation $not_translated = self::_( sprintf( "my string with a %s argument", $argument ) ); // Same thing </pre> == How to not make translators crazy ;) == * When you need the same string twice, try to reuse exactly the same string (with the same case) to minimize the number of strings. * Do not mark as translatable a game element that does not have to be translated (ex: if the name of a monster on a card is "Zzzzz", maybe there's no need to translate it). * Words does not come in the same order in each language. Thus, when you have to translate a string with an argument, do not write something like: <pre>_("First part of the string, ").$argument.' '._("second part of the string")</pre> Write instead: <pre>sprintf( _("First part of the string, %s second part of the string"), $argument )</pre> (or the equivalent "dojo.string.substitute" in Javascript) * When translators are going to translate your game, the most difficult task for them is to get the context of the string to be translated. The more the string is a short insignificant string, the more difficult is the task for them. As a rule of thumb, try to avoid insignificant short strings. * The BGA translation policy is to be flexible on grammar... We prefer to write "player gets 1 coin(s)" than write two versions of the same string for plural and singular - it reduces the number of strings to translate. * Instead of writing nice strings like "With the effect of ZZZ, player XXX gets a new YYY", which is very difficult to translate, write strings like "ZZZ: XXX gets YYY". == On client side (Javascript) == On client side, things are quite simple: you just have to use the "_()" function for all strings you want to translate. Examples: <pre> // Get a string in player's language: var translated = _("original english string"); // Get a string in player's language with parameter: var translated = dojo.string.substitute( _("You can pick ${p} cards and discard ${d}"), { p: 2, d: 4 } ); </pre> '''WARNING:''' in Javascript strings to translate, you should never use '\n', '\t' or such, as it will break the translation bundle and result in all the Javascript translation to fail. In any case, the strings will result in HTML code, and such character codes won't have any impact on the HTML rendering. You should use HTML markup instead. == On server side (PHP) == On PHP side, you can use 3 different functions to specify that a string must be translated. '''clienttranslate( "my string to translate" ):''' This function is '''transparent''': it will return the original English string without any change. It's only purpose is to mark this string as "must be translated", and to make sure the translated version of the string will be available on client side. In general, you use clienttranslate: * On your states.inc.php, for field "description" and "descriptionmyturn". <pre> "description" => clienttranslate('${card_name}: ${actplayer} must discard 4 identical energies'), </pre> * On "material.inc.php", when defining texts for game material that must be displayed on client side. <pre> $this->card_types = array( 1 => array( 'name' => clienttranslate("Amulet of Air"), // Thus, we can use "_( card_name )" on Javascript side. </pre> * When sending a notification with "notifyAllPlayers" or "notifyPlayer", for the game log string and all game log arguments that need a translation. <pre> // A game log string with no argument: self::notifyAllPlayers( 'pickLibraryCards', clienttranslate("Everyone draw cards from his library"), array() ); </pre> Translating arguments is a little bit more complex. It is using the "i18n" special argument as below: <pre> // In the following example, we translate the game log itself, but also the "card_name" argument: self::notifyAllPlayers( 'winPoints', clienttranslate('${card_name}: ${player_name} gains ${points} point(s)'), array( 'i18n' => array( 'card_name' ), // <===== We specify here that "card_name" argument must be transate 'player_id' => $player_id, 'player_name' => self::getActivePlayerName(), 'points' => $points, 'card_name' => $this->card_types[8]['name'] // <==== Here, we provide original English string. ) ); </pre> Pay attention when using 'i18n' argument when translating argument for client : do NOT use same argument for both translation AND key code for client side action (like using 'card_name' to move it on player board as described in the example). It's pretty obvious in the example, but it can be very tricky when translation is made at the end of the development (which is often the case). Use explicit argument name like 'card_name_translated' by example. '''self::_( "my string to translate" ):''' This function returns a string translated in the language of CURRENT user (ie: player who send the request to the server) (be careful, this is NOT the active player). Most of the time, you don't need to translate strings on server side, except on the following 3 situations: * When throwing an exception because the player did a forbidden move. <pre> // This will display a translatable red message to the player that just do some wrong action: throw new BgaUserException( self::_('You must choose 3 cards') ); // ... notice the use of BgaUserException that signals that this exception is "expected". In theory, all exception that are expected should be translated. </pre> * In "yourgame.view.php", when creating the labels for the game interface used in your template (.tpl) file. <pre> $this->tpl['CARDS_FOR_YEAR_2'] = self::_("Your cards for year II"); </pre> * Eventually, in your material.inc.php, if for example you need to use some string elements in your exceptions. <pre> // In material.inc.php, $this->energies[n]['nametr'] has been created with the self::_() method. This we can do this: throw new BgaUserException( self::_("To execute this action you need more: ").' '.$this->energies[$resource_id]['nametr'] ); </pre> * Eventually, in your "getAllDatas" PHP method, as the data return by this method is used only by current user. '''totranslate( "my string to translate" ):''' This function works exactly like 'clienttranslate', except it tells BGA that the string is not needed on client side. You should not use this function, except on the following cases: * Statistics name in stats.inc.php * Option names and option values name in gameoptions.inc.php d57e77d3fa917a20f52851dfdf6a694582eaef6a Game art: img directory 0 89 1932 1417 2016-08-08T00:50:24Z Victoria la 11989 /* Requested images */ wikitext text/x-wiki == Requested images == The following images are requested by BGA: ;game_box.png * It is displayed on the main site on the game description page and when creating a table (280x280 px). * It should be a 3D image of a physical copy of the game box as it appears in an online shop. * It is better to take the version of the game that is coherent with the game art used in the adaptation, and from the original publisher of the game. * The background of the image must be transparent. * If you don't have a 3D version of the game box, you can use the following website to create one: http://www.3d-pack.com/ ;game_box180.png ;game_box72.png * Don't modify these images, they are auto generated by "Reload game box image" action. If you have another copy of your source make sure you update you copy of these files after they have been generated and not override with old copied. ;game_icon.png * It is the icon displayed in the lists of games and tables (50x50 px). * This one should not be transparent, and shouldn't have a border (a black border will be add by BGA). * The objective of this icon is to make the game recognizable among the other games. A good idea is to take a part of the game cover that is distinctive (ex: the game title). ;publisher.png * It is the logo of the publisher of the game, displayed on the game description page. * The width must be 150 px. The height can be anything. The image could be transparent. ;publisher2.png (optional) * If the game has been co-published by 2 publishers, you should upload a second image named "publisher2.png" (same characteristics as the first one). '''Important''': when you modify these images, you MUST click on "Reload game box image" from the Control Panel in order your update can be taken into account. == Game art == You must upload in img directory all images of your game interface. === Images loading === '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. Note that you can tune the way images are loaded with Javascript method "dontPreloadImage" (see [[Game_interface_logic:_yourgamename.js|Game Interface Logic]]). === Images format === You can use 3 image format while building your game interface: ;jpg images should be used for non-transparent images. Jpg are usually lighter than Pngs, so please choose Jpg for big pictures (ex: game board, cards) when you don't need transparency to accelerate game load. ;png images should be used for transparent images. ;gif images can be used for animated images. This is not recommended to use gif animated images as they can upset players, but for some specific interface element this could be useful. === Use CSS Sprites === To limit the number of images load and make the game load faster, you must use CSS sprites, ie you must gather several images in a single one. To learn more on CSS Sprites: * [http://www.w3schools.com/css/css_image_sprites.asp CSS sprites (W3C documentation)]. * [[Game interface stylesheet: yourgamename.css]] 404e9aa2fb1aac7c575c9733d491de7e1529ffe8 Game options and preferences: gameoptions.inc.php 0 219 1933 1875 2016-08-08T01:34:27Z Victoria la 11989 wikitext text/x-wiki In this file, you can define your game options (= game variants) and user preferences. Note: If your game has no variants or preferences, you don't have to modify this file. == Game Options == Game options is something selected by table creator and usually correspond to game variation, for example if game includes expansion or certain special rule. <pre> $game_options = array ( 100 => array ( 'name' => totranslate ( 'my game option' ), 'values' => array ( // A simple value for this option: 1 => array ( 'name' => totranslate ( 'option 1' ) ), // A simple value for this option. // If this value is chosen, the value of "tmdisplay" is displayed in the game lobby 2 => array ( 'name' => totranslate ( 'option 2' ), 'tmdisplay' => totranslate ( 'option 2' ) ), // Another value, with other options: // beta=true => this option is in beta version right now. // nobeginner=true => this option is not recommended for beginners 3 => array ( 'name' => totranslate ( 'option 3' ), 'beta' => true, 'nobeginner' => true ) ) ) ); </pre> Note²: All options defined in this file should have a corresponding "game state labels" with the same ID (see "initGameStateLabels" in yourgame.game.php) self::initGameStateLabels ( array ( ... "my_first_game_variant" => 100, ) ); IMPORTANT: After you edited and deployed this file you have to go to control panel and press "Reload game options configuration" == User Preferences == User preferences is something cosmetic about the game interface which however can create user wars, so you can satisfy all user by giving them individual preferences. Do not use this unless absolutely necessary and usually only after game has been in production for a while. If you add these currently only admins can apply these settings, so you would have to contact them after editing this file. <pre> $game_preferences = array( 100 => array( 'name' => totranslate('Notation style'), 'needReload' => true, // after user changes this preference game interface would auto-reload 'values' => array( 1 => array( 'name' => totranslate( 'Classic' ), 'cssPref' => 'notation_classic' ), 2 => array( 'name' => totranslate( 'Tournament' ), 'cssPref' => 'notation_tournament' ) ) ) ); </pre> There is two ways to check/apply this. In java Script if (this.prefs[100].value == 2) ... This checks if preferences 100 has selected value 2. Second, if cssPref specified it will be applied to the body tag. So you can use different css styling for the preference. As user you have to select them from the Gear menu when game is started. On studio only user0 will have it actually working (bug?). ddec1ab029e13b75305dc9230aa0d3c7f35959d3 Gamehelpeightmastersrevenge 0 163 1940 1671 2016-08-16T18:32:29Z Rondeau1367 14144 /* Overview and aim of the game */ wikitext text/x-wiki ===Overview and aim of the game=== 8 Masters’ Revenge is a fighting game for 1 to 4 players (only available for 2 players on BGA). You are a martial arts master and you want to beat your opponents, strike after strike. Your only weapons are your 2 hands, represented by the 2 cards you have in play. Find the weak point in your opponent’s guard to deal damage to him. As soon as his "health" marker reaches the last space of his life track (whose length depends of the number of players), he is out of the game. The last surviving player wins the fight. Play a specific character Players may decide to play one of the 8 available fighters. Each fighter has two specific martial techniques which he can use when in fury (see “Fighters’ martial techniques” below). A fighter automatically enters the state of “fury” at the beginning of a player’s turn (his turn or an opponent’s) if his 2 cards in play have the same color. He leaves the state of “fury” at the beginning of a player’s turn if his 2 cards in play do not have the same color. ====Turn break down==== =====Active player (attacker)===== The active player can choose to perform one of the following actions: Draw 2 cards (or 1 card if he or she already has 3 cards in hand due to having a handsize limit of 4 cards). After drawing cards the active player may move one token, in his or her area, to an adjacent field. '''Important: A damange token that lies on a emtpy field can only be placed on an adjacent empty field, and a damage token that lies on a card can only be placed on an adjacent card!''' ''Or'' Perform an attack! In order to do so the active player has to place a card from his/her hand in play. This card has to be put adjacent to the two cards already in play. The card that is not adjacent to the new card will be discarded and is the card that performs the attack. Now 5 steps take place: # Apply token effect (if any). # Check if the attack hits! An attack hits if the ''attacker’s attack value'' is '''exactly equal''' to the ''defender’s defense value''. (the attack value is the value created with the new card put in play; more below). # Deal damage if the attack hits. # Apply the effect of the discarded card. # Play an extra turn if a pair was formed with the new card (meaning that the center numbers are equal -> 1/1 2/2 3/3 4/4 5/5). During the extra turn a new attack can be launched or '''1''' card can be drawn. When no new pair is formed or when a card is drawn the turn is passed on the the second player. =====Passive player (defender)===== When the active player launches an attack, the passive player has 3 options if certain conditions are met. <ol> <li>Do nothing and take the blow (shouting: "''that doesn't hurt me!''") <li><b>Block the attack.</b> You can block an attack if you meet the following condition. <ol><li>If you have a card in play that has the same color as the card with which is attacked. (so you can block a yellow card with a yellow card). </li></ol> Blocking will reduce incoming dmg with 1. However, a card used for blocking stays in its blocking state, until it is discarded (used to attack), meaning you cannot use it a second time for blocking and you cannot form a pair with it. Most important if you're attacked a second time with a card of the same color and you still have the card in the blocking area '''you will suffer 2 additional damage'''.</li> <li><b>Counter the attack</b>. You can launch a counter attack on your opponents attack when you meet 2 conditions. <ol><li> you have in play a card with a dragon symbol</li> <li>you have a card in your hand with a dragon symbol</li></ol> If both conditions are met, you can form a dragon pair by playing the dragon card from your hand next to the dragon card you have in play. Be careful, as your opponent may perform a counter attack on your counter attack, if your opponent matches both conditions as well. When the attacker is not able to counter the counter attack his/her turn ends immediately and as such the effects from the card with which was attacked are not applied. (You can continue countering each other until one of you no longer has a card with a dragon symbol, to put in play). </li> </ol> =====Computation of defense and attack values===== The Attack value is equal to the sum of the numbers in the center of the couple of cards you have in play<br/> The Defense value is equal to the sum of the numbers of both ends of the couple of cards you have in play Example: you have a 2-4 and a 5-1 card in play. (2-4/5-1)<br/> Thus attack value = 9 (4+5)<br/> and defense value = 3 (2+1) 8f443e8ca6337d3562d07c77fe9099979cc3aea6 Gamehelpmetromania 0 225 1941 2016-08-22T12:18:14Z 333-blue 13923 Redirected page to [[Gamehelpmetromaniab]] wikitext text/x-wiki #redirect [[Gamehelpmetromaniab]] 6302bf64cc50ef2b39b2237a18dff1b1f2ccbe65 Kaozeadenn Implijer:333-blue 3 226 1942 2016-08-22T12:20:20Z 333-blue 13923 Created page with "&nbsp;" wikitext text/x-wiki &nbsp; 47c1f11ed4d1aad1a1b674bda71a89d4ff562d55 Implijer:333-blue 2 227 1943 2016-08-22T12:20:41Z 333-blue 13923 Created page with "&nbsp;" wikitext text/x-wiki &nbsp; 47c1f11ed4d1aad1a1b674bda71a89d4ff562d55 Gamehelpmetromaniab 0 203 1944 1808 2016-08-22T12:21:34Z 333-blue 13923 /* DESCRIPTION & OBJECTIVE */ wikitext text/x-wiki == DESCRIPTION & OBJECTIVE == Each player represents a subway-building company, and will dig two subway lines across the city. The goal is to connect important destinations – residential areas, commercial areas, and entertainment areas – and to provide them with subway stations. Take advantage of other players lines (for example, stations are built wherever two lines meet ; you can win points at the end by sharing the quickest trip), and try also to deroute or even block off your opponents at the right time, to keep them from well completing their lines! At the end of the game, the city government will run seven "test trips" between designated destinations, placed by the players themselves during the game. For each test trip, the fastest connection between the two points will be rewarded with Public Utility Points, and the player whose subways have the most points wins! == GAME COMPONENTS & SET UP == '''Game Board''' To set up the board, take the four border pieces and put them together. Take the six triangular "city" pieces, and arrange them randomly within the border. '''Counters''' Each player takes a set of counters of a particular color. Each has a score marker (showing a subway train), which is placed on the gameboard on the "0" space of the scoring track. Each player also has counters for two subway lines: one with a solid color, and another with a "striped" color. Each line should have a Start marker (white arrow), an End marker (black arrow), and eighteen triangular Tunnel counters. There are also twelve Destination markers. Each is marked with a letter (A-F), and is paired with another Destination marker. These will be the destinations that will be "tested" after the building phase is complete. The summary of these tests is in the upright corner of the board. Finally, there are thirty "station" markers, which are set by the side of the board, and are not controlled by any player. The map is made up of smaller triangles, which are either blank, have a destination symbol, or a lake/park. Along the edge of the city are white arrows indicating where a subway line starts, and black arrows indicating where they exit the city == THE COURSE OF THE GAME == '''Installation''' Take the destination markers and shuffle them letter-sidedown. With 4 players, each player takes one Residential, one Commercial, and one Entertainment Destination at random. That player then secretly looks at his markers. If two have the same letter, he puts one back and draws a new one until all three have different letters. When all the players have their three Destination markers, they flip them letter-side-up in front of them, visible for others. With 3 players, each player takes one more Destination marker. With 2 players, each player gets 6 Destination markers: one player gets the Destinations A,B,C,D,E,F shown on the left of the gameboard test Summary, the other player uses the ones on the right. '''Player turn''' The most "urbane" player begins. Play goes clockwise starting with the first player. On one's turn, the player MUST do one and only one of the following: - Dig 3 tunnels (to continue one or both of his lines) or - Build an intermediate station (on one of his lines) '''Starting a line''' Each player has two subway lines. On his first turn, a player must, of course, begin a subway line - but only one! A subway line must start from an empty space with a white arrow along the edge of the city. To start a line, place its first tunnel, topped with its "start" marker, in any of these spaces. Then continue normally the line in the city by digging the remaining tunnels. When you will begin your second subway line at any subsequent turn, it must start on one of the "opposite" edges from where your first line began. '''Digging tunnels''' Subway lines are built in the city by placing Tunnels in the triangular spaces. Only one tunnel may be placed in a space, and must conform to the following: - A line must always be built from its terminus; and never "branch off" - A line may not be continued with an acute angle. EXCEPTION: when a line terminates at a station, it may be built out from that station at any angle, even acute. - A line may never make a loop or double back on itself If you choose to dig tunnels on your turn, you MUST place 3 tunnels (unless it is only possible to place fewer). If you have two lines, you may distribute your 3 tunnels between them as you wish. '''Special areas''' The start or end spaces (with an arrow) along the edges of the city can only be used to start or end a line. Tunnel counters may never be placed on the park or the lake. When a player places a tunnel counter on top of a destination area, the player must place immediatly one of his Destination markers on that tunnel piece (of the appropriate type, of course), letter-side up. If a player does not have the appropriate marker, the player may not place that tunnel piece on the destination. Furthermore, each player may only place one destination marker per turn, and two destinations of the same letter cannot touch, either on an angle or on the side. '''Stations''' Most of the stations are created while digging tunnels. A station is immediately placed when: - The line being dug joins another line. In this case, a station is placed where the two lines meet up. - The line, which was running alongside another line, splits off from it. In this case, a station is placed where the line splits off. - When a line, running alongside another line, changes side, NO STATION is placed. The player scores 1 point for each destination area on the board that touches the station. He continues to dig tunnels after placing a station, if he still has some left to build. (i.e., building a station like this does not stop your tunneling.) '''Intermediate stations''' In lieu of digging tunnels, a player may use all his turn to place one station anywhere on one of his lines, between two preexisting stations. A starting or ending marker counts as a station for this purpose. Points are scored as for stations placed while digging tunnels. '''Ending lines''' A line ends on a space with a black arrow. The player digs his last tunnel on that space, topped with an "End Line" counter. A line may not end on the same edge as it started, nor on an adjoining edge to that "start edge," unless all the end spaces on the allowed sides are already taken. When a line ends, that player may immediately place an intermediate station anywhere on the line. However, once a line is completed (with this bonus station), the player may never place an intermediate station on that line again '''End of the building phase''' Players continue building until one of the following occurs: - A player has completed both of his lines - A player places the last station available - Five lines are either completed, or blocked and unable to be completed Note : a line is blocked if it can no longer be extended, typically because all the spaces at its end are already occupied, forbidden, or has run out of tunnels. Then all other players have one last turn to play. After, scoring begins. == THE SCORING PHASE == '''Lines scoring''' First, scores are adjusted as follows: - Players who completed both of their lines lose no station points. - Players who completed only one line lose half their station points (rounded down) - Players who completed none of their lines lose all their station points. Adjust the scoring markers accordingly. '''Test trip scoring''' Each test trip runs between destination markers of the same letter: A to A, then B to B, and so on. You can see the summary of these trips in the upright corner of the board. For each trip, determine the shortest route: - a trip takes 1 minute to go from one station to another (no matter how many tunnel pieces are in between) - and 3 minutes to change from one line to another. A trip may have more than one fastest route. Each player who has a line making up part of the fastest route gets 3 points, plus a bonus of 3 points if he placed one of the destination markers (i.e., if the marker is on a tunnel piece of the player's color). A player may only get points once for each test, even if the player is involved in more than one route. Players who are not involved in the fastest route never get any point. '''Impossible trips''' Sometimes, a test run may be impossible. If that is the case, a city investigation takes place to determine the guilty party or parties: - If the destination marker was never placed on the board, the guilty party is the player who didn't place the marker. - If the marker was placed but nobody put a station touching it, the guilty party is the player who placed the destination. - If the markers were both placed, but no route exists between the two, both players who placed the markers are guilty. The guilty party or parties loose 6 points '''Final test''' The last test run is between the park and the lake. Determine the fastest route, as always. Each player involved in the fastest route gets 5 points. Important note : if your score goes beyond 20 points, move your marker normally, but place one of your tunnels near the 20 to show that. If your score goes below 0 point, place one of your tunnels near the 0. == THE WINNER == At the end of the game, the player with the most points is crowned King of the Subway - i.e., WINS. If there is a tie, the winner is the player who finished the most lines; if there is again a tie, the winner is the player who placed the most tunnels. If there is still a tie, litigation is the only possible solution. == SPECIAL RULES == Two players End of game: 3 lines finished and/or blocked ends the building phase. The other conditions still unchanged. Test trip scoring: the second version of the rules on this topic is not implemented on BGA. Three players End of game: 4 lines finished and/or blocked ends the building phase. The other conditions still unchanged. Test trip scoring: same as with four players. == VARIANTS == Unfair Municipality (3-4 players) Each player keeps his destination markers letter-side-down in front of him. The markers are only revealed when they are placed on a destination area in the city. No Corruption (3-4 players) Ah, everything is straight and clear… Because each player takes pre-etablished destination markers and keeps them in front of him, letter-face-up, of course! 4 players Player 1: A Residential, B Commercial, C Entertainment Player 2: D Residential, A Commercial, E Entertainment Player 3: F Residential, E Commercial, B Entertainment Player 4: C Residential, D Commercial, F Entertainment 3 players : Player 1: A & D Residential, B Commercial, C Entertainment Player 2: C Residential, A & E Commercial, F Entertainment Player 3: F Residential, D Commercial, B & E Entertainment Metromania Official Rulebook, Spiel or Face 5b7ef0ab1e1e272f8cc4e8d793fc50c782b34466 Gamehelpjaipur 0 115 1945 1399 2016-08-24T06:34:24Z Stevelegend 14192 wikitext text/x-wiki In Jaipur, each player has a hand of cards with various (color-coded) goods on them. Each player also has a stack of camel cards (their "herd") which is not considered part of their hand. There are five cards face-up between the players that are available for the players to take. There are 55 goods cards consisting of: * Diamonds x6 * Gold x6 * Silver x6 * Cloth x8 * Spice x8 * Leather x10 * Camels x11 On your turn, you take one of three actions: # '''Take''' a single card or all the camels in the face up row. #: You may take any single goods card from the card row and add it to your hand, or take all the camels in the row and add them to your herd. #: You are limited to having 7 goods cards in your hand, so you may not take a goods card if you already have 7 goods cards in your hand. (Again, your herd does not count toward this limit.) #: The card row is then replenished from the deck so it always has 5 cards at the start of a turn. # '''Trade''' for 2 or more goods cards from the row. #: You may trade goods cards from your hand or camels from your herd for goods cards from the card row. For every one card you trade from your hand or herd, you may pick up one goods card from the row and add it to your hand. #: The cards you traded are added to the card row, so it will still have 5 cards. # '''Sell''' cards to earn points. #: You may sell one or more cards to earn points, but all the cards you sell must be the same color. #: If you are selling Diamonds, Gold, or Silver (the red, yellow, and gray cards) you MUST sell at least two cards. #: Regardless of the type of good, each card you sell lets you take one token of the corresponding color from the bank, starting from the most valuable token. #: If you sell 3 or more goods, you also earn a bonus token from the corresponding pile (for sales of 3,4, or 5+ goods). #: The sold goods cards are discarded. The game continues until either: * Three piles of goods tokens are depleted; OR * The card row cannot be replenished. : At that point, players total the points they have on their earned goods tokens and bonus tokens. : In addition, whichever player has more camels in their herd at the end of the round earns the camel bonus token, worth 5 points. : Whichever player earns more points total wins the round. : Tie-breaker, in order: :* Player with more bonus tokens wins the round; :* Player with more goods tokens wins the round; After the round, the game resets and new hands are dealt. The first player to win two rounds wins the game. 6c436ee15cd667537c0c3f6adfb92284262664dc Contact us 0 9 1947 1794 2016-09-01T11:20:42Z Sourisdudesert 1 /* Postal address */ wikitext text/x-wiki '''Board Game Arena''' is located in France. == Contact e-mail == contact(at)boardgamearena.com We receive '''a lot''' of e-mails. Please do not send us an e-mail in any of these two cases: * If you want to report a bug, please do it in the [http://boardgamearena.com/#!bugs bug reporting system] * If you want to report a player for violation of BGA policy, use the "report this player" button on his/her profile. == Postal address == AD2G Studio SAS 19 rue des Ormeaux 92 260 Fontenay-aux-Roses FRANCE +33 6 17 25 80 34 63592b6bd6ed9556efa09e6025f2c16347e56133 Gamehelpgearnpiston 0 112 1949 1400 2016-09-09T01:10:55Z Senatorhung 4176 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: Choose 1 action from the following. The Action Token placed in the Back Alley cannot be used during the next planning phase. <OL> <LI>Black Market (draw 3 New Parts and keep 1), <LI>Espionage (look at one player's blueprints and take one of them), <LI>Union Muscle (move an Action Token ahead in another location). </OL> *Patent Office: Take 1 New Part, either from the face up parts or from the top of the stack. *Junk Yard: Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (a motor and at least one fuel tank of the same color), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 1a351570cc0b948139408165398e271e2608d505 1950 1949 2016-09-09T01:12:05Z Senatorhung 4176 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. Choose 1 action from the following. <OL> <LI>Black Market (draw 3 New Parts and keep 1), <LI>Espionage (look at one player's blueprints and take one of them), <LI>Union Muscle (move an Action Token ahead in another location). </OL> *Patent Office: Take 1 New Part, either from the face up parts or from the top of the stack. *Junk Yard: Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (a motor and at least one fuel tank of the same color), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. f808b683892e47d354ece6b63b0f289211039926 1951 1950 2016-09-09T01:12:26Z Senatorhung 4176 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley: *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> <LI>Black Market (draw 3 New Parts and keep 1), <LI>Espionage (look at one player's blueprints and take one of them), <LI>Union Muscle (move an Action Token ahead in another location). </OL> *Patent Office: Take 1 New Part, either from the face up parts or from the top of the stack. *Junk Yard: Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. *Workshop: Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (a motor and at least one fuel tank of the same color), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. e13162865026a42099672129dcacf488112dc629 1952 1951 2016-09-09T01:15:46Z Senatorhung 4176 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office and Junk Yard. ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> <LI>Black Market (draw 3 New Parts and keep 1), <LI>Espionage (look at one player's blueprints and take one of them), <LI>Union Muscle (move an Action Token ahead in another location). </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (a motor and at least one fuel tank of the same color), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 199d88c3d8a9c1a199f7cae7e3e2c07c2f4d3979 Gamehelpgearnpiston 0 112 1953 1952 2016-09-09T01:17:09Z Senatorhung 4176 /* ROUND SEQUENCE AND PHASES */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> <LI>Black Market (draw 3 New Parts and keep 1), <LI>Espionage (look at one player's blueprints and take one of them), <LI>Union Muscle (move an Action Token ahead in another location). </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least one engine (a motor and at least one fuel tank of the same color), at least one Gear, at least two Axles and exactly one steering mechanism. * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 0f260123fd8543ff49de383baae6140425d76844 1954 1953 2016-09-09T01:20:28Z Senatorhung 4176 /* REQUIREMENTS OF A COMPLETE AUTOMOBILE */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> <LI>Black Market (draw 3 New Parts and keep 1), <LI>Espionage (look at one player's blueprints and take one of them), <LI>Union Muscle (move an Action Token ahead in another location). </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== * Each automobile requires at least: <UL> <LI> at least ONE engine (consists of a motor and at least one fuel tank of the same color); <LI> at least ONE Gear; <LI> at least TWO Axles; and <LI> exactly ONE steering mechanism. </UL> Further Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 395ae7694da18d1e59b9b2703703d94f84c1ce29 1955 1954 2016-09-09T01:29:34Z Senatorhung 4176 /* REQUIREMENTS OF A COMPLETE AUTOMOBILE */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> <LI>Black Market (draw 3 New Parts and keep 1), <LI>Espionage (look at one player's blueprints and take one of them), <LI>Union Muscle (move an Action Token ahead in another location). </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires at least: <UL> <LI> at least ONE engine (consists of a motor and at least one fuel tank of the same color); <LI> at least ONE Gear; <LI> at least TWO Axles; and <LI> exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 80a38a0930cde64f8580cfb4d9258597ffcf5046 1956 1955 2016-09-09T01:32:36Z Senatorhung 4176 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> <LI>Black Market (draw 3 New Parts and keep 1), <LI>Espionage (look at one player's blueprints and take one of them), <LI>Union Muscle (move an Action Token ahead in another location). </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. (last player to place a token here is the first player in the next round) ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires at least: <UL> <LI> at least ONE engine (consists of a motor and at least one fuel tank of the same color); <LI> at least ONE Gear; <LI> at least TWO Axles; and <LI> exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. f9e64082578be7d0967bb5b7fa466593d2403522 1957 1956 2016-09-09T01:35:35Z Senatorhung 4176 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> <LI>Black Market (draw 3 New Parts and keep 1), <LI>Espionage (look at one player's blueprints and take one of them), <LI>Union Muscle (move an Action Token ahead in another location). </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. The FIRST to select this location will be allowed 3 workshop actions. The SECOND to select this location will be allowed 2 workshop actions. Every further selection of this location will only allow 1 workshop action. The last player to place a token here will be the first player to act in the next round. ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires at least: <UL> <LI> at least ONE engine (consists of a motor and at least one fuel tank of the same color); <LI> at least ONE Gear; <LI> at least TWO Axles; and <LI> exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. c13a7dcc7f17fdb66204a297fc2297a564428c6e 1958 1957 2016-09-09T01:37:07Z Senatorhung 4176 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> <LI>Black Market (draw 3 New Parts and keep 1), <LI>Espionage (look at one player's blueprints and take one of them), <LI>Union Muscle (move an Action Token ahead in another location). </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. The FIRST action token placed in this location provides for 3 workshop actions. The SECOND action token placed in this location provides for 2 workshop actions. Every further action token at this location will only allow 1 workshop action. The last player to place an action token here will be the first player to act in the next round. ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires at least: <UL> <LI> at least ONE engine (consists of a motor and at least one fuel tank of the same color); <LI> at least ONE Gear; <LI> at least TWO Axles; and <LI> exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 1da5b21fcb72c72d83692fd644e54dcbcba9d09b 1959 1958 2016-09-09T11:39:09Z Senatorhung 4176 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> <LI>** Black Market (draw 3 New Parts and keep 1), <LI>** Espionage (look at one player's blueprints and take one of them), <LI>** Union Muscle (move an Action Token ahead in another location). </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. The FIRST action token placed in this location provides for 3 workshop actions. The SECOND action token placed in this location provides for 2 workshop actions. Every further action token at this location will only allow 1 workshop action. The last player to place an action token here will be the first player to act in the next round. ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires at least: <UL> <LI> at least ONE engine (consists of a motor and at least one fuel tank of the same color); <LI> at least ONE Gear; <LI> at least TWO Axles; and <LI> exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 0fa9726bf463910db1974ff146214a6340ec38cd 1960 1959 2016-09-09T11:39:34Z Senatorhung 4176 /* REQUIREMENTS OF A COMPLETE AUTOMOBILE */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> <LI>** Black Market (draw 3 New Parts and keep 1), <LI>** Espionage (look at one player's blueprints and take one of them), <LI>** Union Muscle (move an Action Token ahead in another location). </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. The FIRST action token placed in this location provides for 3 workshop actions. The SECOND action token placed in this location provides for 2 workshop actions. Every further action token at this location will only allow 1 workshop action. The last player to place an action token here will be the first player to act in the next round. ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires at least: <UL> <LI> ** at least ONE engine (consists of a motor and at least one fuel tank of the same color); <LI> ** at least ONE Gear; <LI> ** at least TWO Axles; and <LI> ** exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 2f03b53e0bc666fae9fbf680395a07caad6beaec 1961 1960 2016-09-09T11:42:09Z Senatorhung 4176 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> <LI>Black Market (draw 3 New Parts and keep 1),</LI> <LI>Espionage (look at one player's blueprints and take one of them),</LI> <LI>Union Muscle (move an Action Token ahead in another location).</LI> </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. The FIRST action token placed in this location provides for 3 workshop actions. The SECOND action token placed in this location provides for 2 workshop actions. Every further action token at this location will only allow 1 workshop action. The last player to place an action token here will be the first player to act in the next round. ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires at least: <UL> <LI> ** at least ONE engine (consists of a motor and at least one fuel tank of the same color); <LI> ** at least ONE Gear; <LI> ** at least TWO Axles; and <LI> ** exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 8e5d6fcb87f111c0b244ef3e6f2b4e8e416e4a84 1962 1961 2016-09-09T11:42:34Z Senatorhung 4176 /* REQUIREMENTS OF A COMPLETE AUTOMOBILE */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> <LI>Black Market (draw 3 New Parts and keep 1),</LI> <LI>Espionage (look at one player's blueprints and take one of them),</LI> <LI>Union Muscle (move an Action Token ahead in another location).</LI> </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. The FIRST action token placed in this location provides for 3 workshop actions. The SECOND action token placed in this location provides for 2 workshop actions. Every further action token at this location will only allow 1 workshop action. The last player to place an action token here will be the first player to act in the next round. ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires at least: <UL> <LI> at least ONE engine (consists of a motor and at least one fuel tank of the same color);</LI> <LI> at least ONE Gear;/LI> <LI> at least TWO Axles; and/LI> <LI> exactly ONE steering mechanism./LI> </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. f036d1d32c9708f4ac8a822a4ae907290bb784e3 1963 1962 2016-09-10T01:19:02Z Senatorhung 4176 /* REQUIREMENTS OF A COMPLETE AUTOMOBILE */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> <LI>Black Market (draw 3 New Parts and keep 1),</LI> <LI>Espionage (look at one player's blueprints and take one of them),</LI> <LI>Union Muscle (move an Action Token ahead in another location).</LI> </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. The FIRST action token placed in this location provides for 3 workshop actions. The SECOND action token placed in this location provides for 2 workshop actions. Every further action token at this location will only allow 1 workshop action. The last player to place an action token here will be the first player to act in the next round. ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires at least: <UL> # at least ONE engine (consists of a motor and at least one fuel tank of the same color); # at least ONE Gear; # at least TWO Axles; and # exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 9fe440539c434a70743ba69a8bb3c1cdd0926796 1964 1963 2016-09-10T01:19:21Z Senatorhung 4176 /* REQUIREMENTS OF A COMPLETE AUTOMOBILE */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> <LI>Black Market (draw 3 New Parts and keep 1),</LI> <LI>Espionage (look at one player's blueprints and take one of them),</LI> <LI>Union Muscle (move an Action Token ahead in another location).</LI> </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. The FIRST action token placed in this location provides for 3 workshop actions. The SECOND action token placed in this location provides for 2 workshop actions. Every further action token at this location will only allow 1 workshop action. The last player to place an action token here will be the first player to act in the next round. ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires at least: <UL> # at least ONE engine (consists of a motor and at least one fuel tank of the same color);<BR> # at least ONE Gear;<BR> # at least TWO Axles; and<BR> # exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 6363f50910c6b5abb2f336cf2efd75ff45627ff3 1965 1964 2016-09-10T01:19:49Z Senatorhung 4176 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> # Black Market (draw 3 New Parts and keep 1), # Espionage (look at one player's blueprints and take one of them), # Union Muscle (move an Action Token ahead in another location). </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. The FIRST action token placed in this location provides for 3 workshop actions. The SECOND action token placed in this location provides for 2 workshop actions. Every further action token at this location will only allow 1 workshop action. The last player to place an action token here will be the first player to act in the next round. ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires at least: <UL> # at least ONE engine (consists of a motor and at least one fuel tank of the same color);<BR> # at least ONE Gear;<BR> # at least TWO Axles; and<BR> # exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 4a42a8d7b5a37d11a7fd47500149f1500dfcbf68 1966 1965 2016-09-10T01:20:03Z Senatorhung 4176 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> # Black Market (draw 3 New Parts and keep 1),<BR> # Espionage (look at one player's blueprints and take one of them),<BR> # Union Muscle (move an Action Token ahead in another location).<BR> </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. The FIRST action token placed in this location provides for 3 workshop actions. The SECOND action token placed in this location provides for 2 workshop actions. Every further action token at this location will only allow 1 workshop action. The last player to place an action token here will be the first player to act in the next round. ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires at least: <UL> # at least ONE engine (consists of a motor and at least one fuel tank of the same color);<BR> # at least ONE Gear;<BR> # at least TWO Axles; and<BR> # exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 03b7500018251d5d6a638a1324ee277136450c61 1967 1966 2016-09-10T03:36:03Z Senatorhung 4176 /* REQUIREMENTS OF A COMPLETE AUTOMOBILE */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> # Black Market (draw 3 New Parts and keep 1),<BR> # Espionage (look at one player's blueprints and take one of them),<BR> # Union Muscle (move an Action Token ahead in another location).<BR> </OL> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted. *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted. *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. The FIRST action token placed in this location provides for 3 workshop actions. The SECOND action token placed in this location provides for 2 workshop actions. Every further action token at this location will only allow 1 workshop action. The last player to place an action token here will be the first player to act in the next round. ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires: <UL> # at least ONE engine (consists of a motor and at least one fuel tank of the same color);<BR> # at least ONE Gear;<BR> # at least TWO Axles; and<BR> # exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 493ecc295803d3feeada21fa12482af0ee506505 1990 1967 2016-09-18T08:07:42Z Senatorhung 4176 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> # Black Market (draw 3 New Parts and keep 1),<BR> # Espionage (look at one player's blueprints and take one of them),<BR> # Union Muscle (move an Action Token ahead in another location).<BR> </OL><BR> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted.<BR> *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted.<BR? *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. The FIRST action token placed in this location provides for 3 workshop actions. The SECOND action token placed in this location provides for 2 workshop actions. Every further action token at this location will only allow 1 workshop action. The last player to place an action token here will be the first player to act in the next round.<BR> ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires: <UL> # at least ONE engine (consists of a motor and at least one fuel tank of the same color);<BR> # at least ONE Gear;<BR> # at least TWO Axles; and<BR> # exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. b9566deb4654125e0076d14bf1aea52a139c7455 1991 1990 2016-09-18T08:08:06Z Senatorhung 4176 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> # Black Market (draw 3 New Parts and keep 1),<BR> # Espionage (look at one player's blueprints and take one of them),<BR> # Union Muscle (move an Action Token ahead in another location).<BR> </OL><BR> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted.<BR><BR> *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted.<BR><BR> *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. The FIRST action token placed in this location provides for 3 workshop actions. The SECOND action token placed in this location provides for 2 workshop actions. Every further action token at this location will only allow 1 workshop action. The last player to place an action token here will be the first player to act in the next round. ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires: <UL> # at least ONE engine (consists of a motor and at least one fuel tank of the same color);<BR> # at least ONE Gear;<BR> # at least TWO Axles; and<BR> # exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 0576d3dede57bdd07a55f069c1ae02228a9528a4 1992 1991 2016-09-18T08:13:35Z Senatorhung 4176 /* LOCATION ACTIONS */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> # Black Market (draw 3 New Parts and keep 1)<BR> # Espionage (look at one player's blueprints and take one of them)<BR> # Union Muscle (move an Action Token ahead in another location)<BR> </OL><BR> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted.<BR><BR> *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted.<BR><BR> *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. The FIRST action token placed in this location provides for 3 workshop actions. The SECOND action token placed in this location provides for 2 workshop actions. Every further action token at this location will only allow 1 workshop action. The last player to place an action token here will be the first player to act in the next round. ** Choose action(s) from the following. <OL> # Build (add 1 blueprint from your hand to either the front half or the back half of your automobile)<BR> # Dismantle (remove 1 part from your automobile and discard it)<BR> # Upgrade (replace ANY NUMBER of parts on your automobile with parts of the same type and colour from your hand)<BR> </OL><BR> ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires: <UL> # at least ONE engine (consists of a motor and at least one fuel tank of the same color);<BR> # at least ONE Gear;<BR> # at least TWO Axles; and<BR> # exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it. At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. 5e3932395452566a9dfab5f8f1466320b5444aab Gamehelploveletter 0 228 1968 2016-09-11T15:54:09Z Greenman 1407 Created page with "==Winning== A player wins the game after winning a number of tokens based on the number of players: *2 Players: 7 tokens *3 Players: 5 tokens *4 players: 4 tokens" wikitext text/x-wiki ==Winning== A player wins the game after winning a number of tokens based on the number of players: *2 Players: 7 tokens *3 Players: 5 tokens *4 players: 4 tokens e920c88de88f57bba4adac4bc2673c7750e69c2b 1969 1968 2016-09-11T16:00:57Z Greenman 1407 wikitext text/x-wiki ==Winning== A player wins the game after winning a number of tokens based on the number of players: *2 Players: 7 tokens *3 Players: 5 tokens *4 players: 4 tokens ==The People== *8: princess annette - If you discard the Princess—no matter how or why—she has tossed your letter into the fire. You are knocked out of the round. *7: countess wilhelmina - Unlike other cards, which take effect when discarded, the text on the Countess applies while she is in your hand. In fact, she has no effect when you discard her. If you ever have the Countess and either the King or Prince in your hand, you must discard the Countess. You do not have to reveal the other card in your hand. Of course, you can also discard the Countess even if you do not have a royal family member in your hand. She likes to play mind games.... *6: king arnaud iv - When you discard King Arnaud IV, trade the card in your hand with the card held by another player of your choice. You cannot trade with a player who is out of the round, nor with someone protected by the Handmaid. If all other players still in the round are protected by the Handmaid, this card does nothing. *5: prince arnaud - When you discard Prince Arnaud, choose one player still in the round (including yourself). That player discards his or her hand (do not apply its effect) and draws a new card. If the deck is empty, that player draws the card that was removed at the start of the round. If all other players are protected by the Handmaid, you must choose yourself. *4: handmaid susannah - When you discard the Handmaid, you are immune to the effects ofother players’ cards until the start of your next turn. If all players other than the player whose turn it is are protected by Susannah, the player must choose him- or herself if possible. *3: baron talus - When discarded, choose one other player still in the round. You and that player secretly compare your hands. The player with the lower rank is knocked out of the round. In case of a tie, nothing happens. If all other players still in the round are protected by the Handmaid, this card does nothing. *2: priest tomas - When you discard the Priest, you can look at one other player’s hand. Do not reveal the hand to all players. *1: guard odette - When you discard the Guard, choose a player and name a card (other than Guard). If that player has that card, that player is knocked out of the round. If all other players still in the round are protected by the Handmaid, this card does nothing. 3043723dfc1042c95b24646e1b676f032df172cb 1972 1969 2016-09-15T05:18:01Z 333-blue 13923 /* Winning */ wikitext text/x-wiki ==Winning== A player wins the game after winning a number of tokens based on the number of players: *2 Players: 7 tokens (not allowed) *3 Players: 5 tokens *4 players: 4 tokens ==The People== *8: princess annette - If you discard the Princess—no matter how or why—she has tossed your letter into the fire. You are knocked out of the round. *7: countess wilhelmina - Unlike other cards, which take effect when discarded, the text on the Countess applies while she is in your hand. In fact, she has no effect when you discard her. If you ever have the Countess and either the King or Prince in your hand, you must discard the Countess. You do not have to reveal the other card in your hand. Of course, you can also discard the Countess even if you do not have a royal family member in your hand. She likes to play mind games.... *6: king arnaud iv - When you discard King Arnaud IV, trade the card in your hand with the card held by another player of your choice. You cannot trade with a player who is out of the round, nor with someone protected by the Handmaid. If all other players still in the round are protected by the Handmaid, this card does nothing. *5: prince arnaud - When you discard Prince Arnaud, choose one player still in the round (including yourself). That player discards his or her hand (do not apply its effect) and draws a new card. If the deck is empty, that player draws the card that was removed at the start of the round. If all other players are protected by the Handmaid, you must choose yourself. *4: handmaid susannah - When you discard the Handmaid, you are immune to the effects ofother players’ cards until the start of your next turn. If all players other than the player whose turn it is are protected by Susannah, the player must choose him- or herself if possible. *3: baron talus - When discarded, choose one other player still in the round. You and that player secretly compare your hands. The player with the lower rank is knocked out of the round. In case of a tie, nothing happens. If all other players still in the round are protected by the Handmaid, this card does nothing. *2: priest tomas - When you discard the Priest, you can look at one other player’s hand. Do not reveal the hand to all players. *1: guard odette - When you discard the Guard, choose a player and name a card (other than Guard). If that player has that card, that player is knocked out of the round. If all other players still in the round are protected by the Handmaid, this card does nothing. d42cfa7a1078bdfe6106445a86a275c362004663 1973 1972 2016-09-15T05:19:18Z 333-blue 13923 /* The People */ wikitext text/x-wiki ==Winning== A player wins the game after winning a number of tokens based on the number of players: *2 Players: 7 tokens (not allowed) *3 Players: 5 tokens *4 players: 4 tokens ==The People== *8: princess annette – If you discard the Princess—no matter how or why—she has tossed your letter into the fire. You are knocked out of the round. *7: countess wilhelmina – Unlike other cards, which take effect when discarded, the text on the Countess applies while she is in your hand. In fact, she has no effect when you discard her. If you ever have the Countess and either the King or Prince in your hand, you must discard the Countess. You do not have to reveal the other card in your hand. Of course, you can also discard the Countess even if you do not have a royal family member in your hand. She likes to play mind games. *6: king arnaud iv – When you discard King Arnaud IV, trade the card in your hand with the card held by another player of your choice. You cannot trade with a player who is out of the round, nor with someone protected by the Handmaid. If all other players still in the round are protected by the Handmaid, this card does nothing. *5: prince arnaud – When you discard Prince Arnaud, choose one player still in the round (including yourself). That player discards his or her hand (do not apply its effect) and draws a new card. If the deck is empty, that player draws the card that was removed at the start of the round. If all other players are protected by the Handmaid, you must choose yourself. *4: handmaid susannah – When you discard the Handmaid, you are immune to the effects ofother players’ cards until the start of your next turn. If all players other than the player whose turn it is are protected by Susannah, the player must choose him- or herself if possible. *3: baron talus – When discarded, choose one other player still in the round. You and that player secretly compare your hands. The player with the lower rank is knocked out of the round. In case of a tie, nothing happens. If all other players still in the round are protected by the Handmaid, this card does nothing. *2: priest tomas – When you discard the Priest, you can look at one other player’s hand. Do not reveal the hand to all players. *1: guard odette – When you discard the Guard, choose a player and name a card (other than Guard). If that player has that card, that player is knocked out of the round. If all other players still in the round are protected by the Handmaid, this card does nothing. 24a3c7e346b3c01a4c63c572cb45439353bd1819 1993 1973 2016-09-18T22:48:32Z Mrwatchdog 11250 wikitext text/x-wiki ==Winning== A player wins the game after winning a number of tokens based on the number of players: *2 Players: 7 tokens (not allowed on BGA so far) *3 Players: 5 tokens *4 players: 4 tokens ==The Game== One of the 16 cards is removed at the beginning of the game and the others are shuffled. Every player gets 1 card and the remain cards form a pile in the center of the table. Players take turns drawing one card (making two cards in hand) and discarding one card (going back to one card in hand). When you discard a card, you apply its effect (see the following section). The round ends either when there is no cards left in the deck for a player to draw or when all but one player are knocked out. The player holding the card with the highest rank earns 1 token. If there is a tie, the tiebreaker will be the sum of the value of the cards each player discarded in the game. If the tie remains, nobody gets a token. ==The Cards== *8: Princess Annette – If you discard the Princess — no matter how or why — she has tossed your letter into the fire. You are knocked out of the round. (1 card) *7: Countess Wilhelmina – Unlike other cards which take effect when discarded, the text on the Countess applies while she is in your hand. In fact, she has no effect when you discard her. If you ever have the Countess and either the King or Prince in your hand, you must discard the Countess. You do not have to reveal the other card in your hand. Of course, you can also discard the Countess even if you do not have a royal family member in your hand. She likes to play mind games. (1 card) *6: King Arnaud IV – When you discard King Arnaud IV, trade the card in your hand with the card held by another player of your choice. You cannot trade with a player who is out of the round, nor with someone protected by the Handmaid. If all other players still in the round are protected by the Handmaid, this card does nothing. (1 card) *5: Prince Arnaud – When you discard Prince Arnaud, choose one player still in the round (including yourself). That player discards his or her hand (do not apply its effect, unless it's Princess Annette) and draws a new card. If the deck is empty, that player draws the card that was removed at the start of the round. If all other players are protected by the Handmaid, you must choose yourself. (2 cards) *4: Handmaid Susannah – When you discard the Handmaid, you are immune to the effects of other players’ cards until the start of your next turn. (2 cards) *3: Baron Talus – When discarded, choose one other player still in the round. You and that player secretly compare your hands. The player with the lower rank is knocked out of the round. In case of a tie, nothing happens. If all other players still in the round are protected by the Handmaid, this card does nothing. (2 cards) *2: Priest Tomas – When you discard the Priest, you can look at one other player’s hand. DO NOT reveal the hand to all players. (2 cards) *1: Guard Odette – When you discard the Guard, choose a player and name a card (other than Guard). If that player has that card, that player is knocked out of the round. If all other players still in the round are protected by the Handmaid, this card does nothing. (5 cards) ==Tips!== Some cards combination lead to odd situations and you should be aware of them: * Princess + King = You will be forced to trade the Princess with somebody else. * Princess + Prince (and everyone else is protected) = You will be forced to play the Prince on yourself and toss the Princess (therefore, lose). Keep in mind how many Prince cards are left in the deck. When a player uses the Prince, one more card from the deck is used. So, keep that in mind to not be tricked in the deck count. 72f1a3c175fd21aba299011d4935701ea8744539 1994 1993 2016-09-18T22:49:04Z Mrwatchdog 11250 wikitext text/x-wiki ===Winning=== A player wins the game after winning a number of tokens based on the number of players: *2 Players: 7 tokens (not allowed on BGA so far) *3 Players: 5 tokens *4 players: 4 tokens ===The Game=== One of the 16 cards is removed at the beginning of the game and the others are shuffled. Every player gets 1 card and the remain cards form a pile in the center of the table. Players take turns drawing one card (making two cards in hand) and discarding one card (going back to one card in hand). When you discard a card, you apply its effect (see the following section). The round ends either when there is no cards left in the deck for a player to draw or when all but one player are knocked out. The player holding the card with the highest rank earns 1 token. If there is a tie, the tiebreaker will be the sum of the value of the cards each player discarded in the game. If the tie remains, nobody gets a token. ===The Cards=== *8: Princess Annette – If you discard the Princess — no matter how or why — she has tossed your letter into the fire. You are knocked out of the round. (1 card) *7: Countess Wilhelmina – Unlike other cards which take effect when discarded, the text on the Countess applies while she is in your hand. In fact, she has no effect when you discard her. If you ever have the Countess and either the King or Prince in your hand, you must discard the Countess. You do not have to reveal the other card in your hand. Of course, you can also discard the Countess even if you do not have a royal family member in your hand. She likes to play mind games. (1 card) *6: King Arnaud IV – When you discard King Arnaud IV, trade the card in your hand with the card held by another player of your choice. You cannot trade with a player who is out of the round, nor with someone protected by the Handmaid. If all other players still in the round are protected by the Handmaid, this card does nothing. (1 card) *5: Prince Arnaud – When you discard Prince Arnaud, choose one player still in the round (including yourself). That player discards his or her hand (do not apply its effect, unless it's Princess Annette) and draws a new card. If the deck is empty, that player draws the card that was removed at the start of the round. If all other players are protected by the Handmaid, you must choose yourself. (2 cards) *4: Handmaid Susannah – When you discard the Handmaid, you are immune to the effects of other players’ cards until the start of your next turn. (2 cards) *3: Baron Talus – When discarded, choose one other player still in the round. You and that player secretly compare your hands. The player with the lower rank is knocked out of the round. In case of a tie, nothing happens. If all other players still in the round are protected by the Handmaid, this card does nothing. (2 cards) *2: Priest Tomas – When you discard the Priest, you can look at one other player’s hand. DO NOT reveal the hand to all players. (2 cards) *1: Guard Odette – When you discard the Guard, choose a player and name a card (other than Guard). If that player has that card, that player is knocked out of the round. If all other players still in the round are protected by the Handmaid, this card does nothing. (5 cards) ===Tips!=== Some cards combination lead to odd situations and you should be aware of them: * Princess + King = You will be forced to trade the Princess with somebody else. * Princess + Prince (and everyone else is protected) = You will be forced to play the Prince on yourself and toss the Princess (therefore, lose). Keep in mind how many Prince cards are left in the deck. When a player uses the Prince, one more card from the deck is used. So, keep that in mind to not be tricked in the deck count. 67575d81a9cbf5e9cc28f1eb843f8084f0767bfc Deck 0 101 1970 654 2016-09-14T05:01:42Z Yami-sakana 4412 /* Shuffling */ wikitext text/x-wiki "Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side. Using "deck", you will be able to use the following features without writing a single SQL database request: * Place cards in pile, shuffle cards, draw cards one by one or many by many. * "Auto-reshuffle" discard pile into deck when deck is empty. * Move cards between different locations: hands of players, the table, ... == Using Deck: Hearts example == Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times. == Deck overview == With Deck component, you manage all cards of your game. === The 5 properties of each card === Using Deck component, each card will have 5 properties: * '''id''': This is the unique ID of each card. * '''type''' and '''type_arg''': These two values defines the type of your card (=what sort of card this is?). * '''location''' and '''location_arg''': These two values defines where is the card at now. id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area. '''id''' is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game. '''type''' and '''type_arg''' defines the type of your card. '''type''' is a short string, and '''type_arg''' is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below. Examples of usage of "type" and "type_arg": * In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K). * In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used. * In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile. '''location''' and '''location_arg''' defines where is the card at now. '''location''' is a short string, and '''location_arg''' is an integer. You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs: * 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn). * 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player. * 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle"). Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game. === Create a new Deck component === For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql": <pre> CREATE TABLE IF NOT EXISTS `card` ( `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `card_type` varchar(16) NOT NULL, `card_type_arg` int(11) NOT NULL, `card_location` varchar(16) NOT NULL, `card_location_arg` int(11) NOT NULL, PRIMARY KEY (`card_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; </pre> Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method: <pre> $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); </pre> Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game). Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method. "Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts": <pre> // Create cards $cards = array(); foreach( $this->colors as $color_id => $color ) // spade, heart, diamond, club { for( $value=2; $value<=14; $value++ ) // 2, 3, 4, ... K, A { $cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1); } } $this->cards->createCards( $cards, 'deck' ); </pre> As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument). Now, you are ready to use "Deck"! === Simple examples using Deck === (Most examples are from "Hearts" game) <pre> // In "getAllDatas', we need to send to the current player all the cards he has in hand: $result['hand'] = $this->cards->getCardsInLocation( 'hand', $player_id ); </pre> <pre> // At some time we want to check if all the cards (52) are in player's hands: if( $this->cards->countCardInLocation( 'hand' ) == 52 ) // do something </pre> <pre> // When a player plays a card in front of him on the table: $this->cards->moveCard( $card_id, 'cardsontable', $player_id ); // Note the use of the custom location 'cardsontable' here to keep track of cards on the table. </pre> <pre> // This is a new hand: let's gather all cards from everywhere in the deck: $this->cards->moveAllCardsInLocation( null, "deck" ); // And then shuffle the deck $this->cards->shuffle( 'deck' ); // And then deal 13 cards to each player // Deal 13 cards to each players // Create deck, shuffle it and give 13 initial cards $players = self::loadPlayersBasicInfos(); foreach( $players as $player_id => $player ) { $cards = $this->cards->pickCards( 13, 'deck', $player_id ); // Notify player about his cards self::notifyPlayer( $player_id, 'newHand', '', array( 'cards' => $cards ) ); } // Note the use of "notifyPlayer" instead of "notifyAllPlayers": new cards is a private information ;) </pre> == Deck component reference == === Initializing Deck component === '''init( $table_name )''' Initialize the Deck component. Argument: * table_name: name of the DB table used by this Deck component. Must be called before any other Deck method. Usually, init is called in your game constructor. Example with Hearts: <pre> function Hearts( ) { (...) $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" ); } </pre> '''createCards( $cards, $location='deck', $location_arg=null )''' Create card items in your deck component. Usually, all card items are created once, during the setup phase of the game. "cards" describe all cards that need to be created. "cards" is an array with the following format: <pre> // Create 1 card of type "1" with type_arg=99, // and 4 cards of type "2" with type_arg=12, // and 2 cards of type "3" with type_arg=33 $cards = array( array( 'type' => 1, 'type_arg' => 99, nbr' => 1 ), array( 'type' => 2, 'type_arg' => 12, nbr' => 4 ), array( 'type' => 3, 'type_arg' => 33, nbr' => 2 ) ... ); </pre> Note: During the "createCards" process, Deck generate unique IDs for all card items. Note: createCards is optimized to create a lot of cards at once. Do not use it to create cards one by one. If "location" and "location_arg" arguments are not set, newly created cards are placed in the "deck" location. If "location" (and optionally location_arg) is specified, cards are created for this specific location. === Card standard format === When Deck component methods are returning one or several cards, the following format is used: <pre> array( 'id' => .., // the card ID 'type' => .., // the card type 'type_arg' => .., // the card type argument 'location' => .., // the card location 'location_arg' => .. // the card location argument ); </pre> === Picking cards === '''pickCard( $location, $player_id )''' Pick a card from a "pile" location (ex: "deck") and place it in the "hand" of specified player. Return the card picked or "null" if there are no more card in given location. This method supports auto-reshuffle (see "auto-reshuffle" below). '''pickCards( $nbr, $location, $player_id )''' Pick "$nbr" cards from a "pile" location (ex: "deck") and place them in the "hand" of specified player. Return an array with the cards picked, or "null" if there are no more card in given location. Note that the number of cards picked can be less than "$nbr" in case there are not enough cards in the pile location. This method supports auto-reshuffle (see "auto-reshuffle" below). In case there are not enough cards in the pile, all remaining cards are picked first, then the auto-reshuffle is triggered, then the other cards are picked. '''pickCardForLocation( $from_location, $to_location, $location_arg=0 )''' This method is similar to 'pickCard', except that you can pick a card for any sort of location and not only the "hand" location. * from_location is the "pile" style location from where you are picking a card. * to_location is the location where you will place the card picked. * if "location_arg" is specified, the card picked will be set with this "location_arg". This method supports auto-reshuffle (see "auto-reshuffle" below). '''pickCardsForLocation( $nbr, $from_location, $to_location, $location_arg=0, $no_deck_reform=false )''' This method is similar to 'pickCards', except that you can pick cards for any sort of location and not only the "hand" location. * from_location is the "pile" style location from where you are picking some cards. * to_location is the location where you will place the cards picked. * if "location_arg" is specified, the cards picked will be set with this "location_arg". * if "no_deck_reform" is set to "true", the auto-reshuffle feature is disabled during this method call. This method supports auto-reshuffle (see "auto-reshuffle" below). === Moving cards === '''moveCard( $card_id, $location, $location_arg=0 )''' Move the specific card to given location. * card_id: ID of the card to move. * location: location where to move the card. * location_arg: if specified, location_arg where to move the card. If not specified "location_arg" will be set to 0. '''moveCards( $cards, $location, $location_arg )''' Move the specific cards to given location. * cards: an array of IDs of cards to move. * location: location where to move the cards. * location_arg: if specified, location_arg where to move the cards. If not specified "location_arg" will be set to 0. '''insertCard( $card_id, $location, $location_arg )''' Move a card to a specific "pile" location where card are ordered. If location_arg place is already taken, increment all cards after location_arg in order to insert new card at this precise location. (note: insertCardOnExtremePosition method below is more useful in most of the case) '''insertCardOnExtremePosition( $card_id, $location, $bOnTop )''' Move a card on top or at bottom of given "pile" type location. '''moveAllCardsInLocation( $from_location, $to_location, $from_location_arg=null, $to_location_arg=0 )''' Move all cards in specified "from" location to given location. * from_location: where to take the cards * to_location: where to put the cards * from_location (optional): if specified, only cards with given "location_arg" are moved. * to_location (optional): if specified, cards moved "location_arg" is set to given value. Otherwise location_arg is set to zero. Note: if you want to keep "location_arg" untouched, you should use "moveAllCardsInLocationKeepOrder" below. '''moveAllCardsInLocationKeepOrder( $from_location, $to_location )''' Move all cards in specified "from" location to given "to" location. This method does not modify the "location_arg" of cards. '''playCard( $card_id )''' Move specified card at the top of the "discard" location. Note: this is an alias for: insertCardOnExtremePosition( $card_id, "discard", true ) === Get cards informations === '''getCard( $card_id )''' Get specific card information. Return null if this card is not found. '''getCards( $cards_array )''' Get specific cards information. cards_array is an array of cards ID. If some cards are not found or if some cards IDs are specified multiple times, the method throws an (unexpected) Exception. '''getCardsInLocation( $location, $location_arg = null, $order_by = null )''' Get all cards in specific location, as an array. Return an empty array if the location is empty. * location (string): the location where to get the cards. * location_arg (optional): if specified, return only cards with the specified "location_arg". * order_by (optional): if specified, returned cards are ordered by the given database field. Example: "card_id" or "card_type". '''countCardInLocation( $location, $location_arg=null )''' Return the number of cards in specified location. * location (string): the location where to count the cards. * location_arg (optional): if specified, count only cards with the specified "location_arg". '''countCardsInLocations()''' Return the number of cards in each location of the game. The method returns an associative array with the format "location" => "number of cards". Example: <pre> array( 'deck' => 12, 'hand' => 21, 'discard' => 54, 'ontable' => 3 ); </pre> '''countCardsByLocationArgs( $location )''' Return the number of cards in each "location_arg" for the given location. The method returns an associative array with the format "location_arg" => "number of cards". Example: count the number of cards in each player's hand: <pre> countCardsByLocationArgs( 'hand' ); // Result: array( 122345 => 5, // player 122345 has 5 cards in hand 123456 => 4 // and player 123456 has 4 cards in hand ); </pre> '''getPlayerHand( $player_id )''' Get all cards in given player hand. Note: This is an alias for: getCardsInLocation( "hand", $player_id ) '''getCardOnTop( $location )''' Get the card on top of the given ("pile" style) location, or null if the location is empty. Note that the card pile won't be "auto-reshuffled" if there is no more card available. '''getCardsOnTop( $nbr, $location )''' Get the "$nbr" cards on top of the given ("pile" style) location. The method return an array with at most "$nbr" elements (or a void array if there is no card in this location). Note that the card pile won't be "auto-reshuffled" if there is not enough cards available. '''getExtremePosition( $bGetMax ,$location )''' (rarely used) Get the position of cards at the top of the given location / at the bottom of the given location. Of course this method works only on location in "pile" where you are using "location_arg" to specify the position of each card (example: "deck" location). If bGetMax=true, return the location of the top card of the pile. If bGetMax=false, return the location of the bottom card of the pile. '''getCardsOfType( $type, $type_arg=null )''' Get all cards of a specific type (rarely used). Return an array of cards, or an empty array if there is no cards of the specified type. * type: the type of cards * type_arg: if specified, return only cards with the specified "type_arg". === Shuffling === '''shuffle( $location )''' Shuffle all cards in specific location. Shuffle only works on locations where cards are on a "pile" (ex: "deck"). Please note that all "location_arg" will be reset to reflect the new order of the cards in the pile. 8f7de825098013035e0c83e6b5708ddbb871b1dc Gamehelpmancala 0 229 1971 2016-09-15T05:17:31Z 333-blue 13923 Created page with "A canceled game." wikitext text/x-wiki A canceled game. 2ab29e555c41f651406a05ba4eef4a16d5e1fe75 Gamehelpjumpgate 0 137 1974 990 2016-09-15T21:51:03Z Mattworden 4068 /* Scoring Referece */ wikitext text/x-wiki Jump Gate == Turn Reference == Take two actions on your turn. You may take the same action twice. Fly ... to a neighboring planet. Jump ... to another more distant planet. Scan ... your current planet if it has any face-down resources. Land & Claim ... your current planet if it has no face-down resources and is unclaimed. Harvest ... 1 reource you marked with a Scan, or 1 unmarked resource at a planet with all face-up resources. Research ... refill your hand up to 5 cards. You may discard any number of cards before refilling. == Scoring Reference == If there are 7 or more markers on the Black Hole, the player(s) with the most markers on the Black Hole must discard their hidden resource cards before scoring. Otherwise, players reveal their hidden resource cards and add them to their collected resources for scoring. Score all collected resources as explained on the resource cards. Add 4 points for each planet claimed. Player with the highest score wins. 8c09af4319374e129e047ee9b9f2ada94e09ad9d 1975 1974 2016-09-15T21:56:28Z Mattworden 4068 wikitext text/x-wiki == Jump Gate == The Jump Gate has just been invented, and it allows a ship to jump into orbit around a distant planet in an instant. This puts deep space on the map for those willing to make the trip. As a spaceship captain, you've assembled your crew, prepared your ship, and are ready to venture forth. It's time to gaze up upon worlds that no other person has ever seen. ---- Jump Gate is a light space exploration, hand management, and set collection game. Jump between planets, scan for resources, and collect sets that will score you the most points. == Turn Reference == Take two actions on your turn. You may take the same action twice. Actions: - Fly ... to a neighboring planet. - Jump ... to another more distant planet. - Scan ... your current planet if it has any face-down resources. - Land & Claim ... your current planet if it has no face-down resources and is unclaimed. - Harvest ... 1 reource you marked with a Scan, or 1 unmarked resource at a planet with all face-up resources. - Research ... refill your hand up to 5 cards. You may discard any number of cards before refilling. == Scoring Reference == If there are 7 or more markers on the Black Hole, the player(s) with the most markers on the Black Hole must discard their hidden resource cards before scoring. Otherwise, players reveal their hidden resource cards and add them to their collected resources for scoring. Score all collected resources as explained on the resource cards. Add 4 points for each planet claimed. Player with the highest score wins. 8b1e7fc27f89dc99235ea7f7d90eca2d6d44b5a4 1976 1975 2016-09-15T21:57:00Z Mattworden 4068 /* Jump Gate */ wikitext text/x-wiki == Jump Gate == The Jump Gate has just been invented, and it allows a ship to jump into orbit around a distant planet in an instant. This puts deep space on the map for those willing to make the trip. As a spaceship captain, you've assembled your crew, prepared your ship, and are ready to venture forth. It's time to gaze up upon worlds that no other person has ever seen. Jump Gate is a light space exploration, hand management, and set collection game. Jump between planets, scan for resources, and collect sets that will score you the most points. == Turn Reference == Take two actions on your turn. You may take the same action twice. Actions: - Fly ... to a neighboring planet. - Jump ... to another more distant planet. - Scan ... your current planet if it has any face-down resources. - Land & Claim ... your current planet if it has no face-down resources and is unclaimed. - Harvest ... 1 reource you marked with a Scan, or 1 unmarked resource at a planet with all face-up resources. - Research ... refill your hand up to 5 cards. You may discard any number of cards before refilling. == Scoring Reference == If there are 7 or more markers on the Black Hole, the player(s) with the most markers on the Black Hole must discard their hidden resource cards before scoring. Otherwise, players reveal their hidden resource cards and add them to their collected resources for scoring. Score all collected resources as explained on the resource cards. Add 4 points for each planet claimed. Player with the highest score wins. aa7bcaf565ec6bc57d551ba0560625b7302d6d25 Gamehelplheuredesombres 0 230 1977 2016-09-16T11:52:57Z Bigornot 14295 Created page with "Coopératif • À partir de 8 ans • 2 à 4 joueurs • 30 minutes == L'histoire == Une ombre plane sur Ménilville : Elvyr Ozbaum, mandrakologue pourtant expérimenté, a ..." wikitext text/x-wiki Coopératif • À partir de 8 ans • 2 à 4 joueurs • 30 minutes == L'histoire == Une ombre plane sur Ménilville : Elvyr Ozbaum, mandrakologue pourtant expérimenté, a libéré par inadvertance un démon des limbes. Ce mauvais génie s’est échappé et il est parvenu à se glisser dans l’esprit d’un des habitants du quartier. Depuis, il prend un malin plaisir à hypnotiser d’autres victimes innocentes afin de les pousser à faire n’importe quoi... Mais il y a plus inquiétant : s’il n’est pas chassé avant l’heure des 3 ombres, il prendra définitivement possession de son corps d’emprunt ! Voici un défi pour vous, intrépides enquêteurs de l’Agence 3ID : il vous faut au plus vite découvrir en qui se cache le démon des limbes avant qu’il ne dévore l’âme de sa victime et ne devienne à jamais son double maléfique. Mais avec le chat Hercule qui traîne dans vos pattes et le risque de vous faire envoûter à votre tour, la partie est loin d’être gagnée ! L'heure des 3 ombres est tiré de l'univers de Lucile Finemouche & Le Balafré, éditions Actes Sud Junior. == But du jeu == Sur le principe simple du Memory, il s’agit de reconstituer toutes les paires de personnages afin de déterminer celui dont le double n’est pas en jeu. Les joueurs incarnent des enquêteurs qui doivent coordonner leurs recherches dans Ménilville afin d’écarter un à un les suspects et ainsi débusquer le démon qui se cache parmi eux. Si l’horloge atteint l’heure des 3 ombres (12ème heure), la partie est perdue pour TOUS. Si 13 suspects sont écartés, le démon est démasqué et la partie est gagnée pour TOUS. == Tour de jeu == À son tour, un joueur doit lancer le dé Enquête puis appliquer son résultat. • Faces Réverbère / Chapeau / Pentacle / Rouage : le joueur dévoile 1 tuile du Lieu désigné par le dé et 1 tuile de son choix (du même Lieu ou d’un autre Lieu) ; si le Lieu désigné ne contient aucune tuile, le joueur ne peut dévoiler qu’1 seule tuile de son choix ; • Face Loupe : le joueur dévoile 2 tuiles de son choix ; • Face Horloge : l’Horloge avance puis le joueur dévoile 2 tuiles de son choix. ATTENTION : chaque Suspect existe en 2 versions (normale et hypnotisée), très proches visuellement l’une de l’autre . Il est donc très facile de les confondre ! Si le joueur dévoile 2 Suspects strictement identiques : • Il place les 2 tuiles en pile faces visibles à un emplacement libre du plateau Agence 3ID ; il parvient à innocenter un suspect et le mène illico à l’Agence afin qu’il y soit en sécurité ; • Il pioche une carte 3ID ; de retour au bureau, il récupère du matériel ; • Puis il prend, sans la regarder, 1 tuile Traquenard disponible et la place, face cachée, à un emplacement libre d’un Lieu de son choix ; durant l’absence de l’enquêteur, le démon en profite pour étendre son pouvoir sur Ménilville... Si le joueur dévoile 2 Suspects différents : • Il retourne les tuiles visibles faces cachées ; • Il peut, s’il le souhaite, y placer des Indices de sa réserve ; s’il n’a pas réussi à écarter de suspect, il a tout de même récolté quelques informations ; • Puis il pioche une carte Limbes ; le sort s’acharne ! Si le joueur dévoile 1 Traquenard : • S’il a dévoilé le Traquenard en premier, il en applique immédiatement l’effet sans dévoiler d’autre tuile ; • S’il a dévoilé le Traquenard en second, il retourne face cachée l’autre tuile Suspect qui a été dévoilée avant d’appliquer l’effet du Traquenard ; • Puis il défausse le Traquenard. Une fois son tour effectué, c’est au joueur à sa gauche de lancer le dé Enquête. == Indices == • S’il dévoile 2 Suspects différents, un joueur peut, s’il le souhaite, y laisser des Indices de sa réserve après les avoir retournés faces cachées ; une tuile ne peut accueillir qu’un seul Indice. • Un Indice placé sur une tuile sert simplement à marquer un Suspect, comme un pense-bête laissé en évidence : aux joueur de se souvenir de ce qu’il y a en dessous. • Si un joueur n’a plus d’Indice en réserve, il peut décider de déplacer ses Indices déjà présents sur les Lieux. • Quand une tuile porteuse d’un Indice est dévoilée, l’Indice retourne dans la réserve de son Enquêteur. • Quand une tuile porteuse d’un Indice est regardée secrètement, l’Indice reste sur la tuile. == Traquenards == Si le joueur dévoile 1 Traquenard, il doit en appliquer les effets : • Hercule : ce satané matou prend un malin plaisir à ralentir l’enquête ; le joueur jette 2 cubes Hercule vers le centre des 4 Lieux ; chaque cube Hercule est placé sur la tuile libre face cachée objectivement la plus proche ; une tuile porteuse d’un cube Hercule ne peut être ni regardée, ni dévoilée, ni mélangée ; à son tour, à la place de dévoiler 1 tuile, un joueur peut désigner 1 tuile porteuse d’un cube Hercule pour défausser le cube sans la dévoiler ; ainsi, la tuile est de nouveau accessible ; s’il n’y a plus de cubes Hercule disponibles, l’Horloge avance et le Traquenard est défaussé ; • Yeux du démon : le malheureux enquêteur croise le regard du démon, sa tête lui tourne et il s’évanouit ; le joueur tourne d’1/4 de tour dans le sens horaire le plateau Lieu de la couleur indiquée sur les Yeux du démon ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Vortex : l’enquêteur entrouvre une faille vers les limbes, la réalité en est toute chamboulée ; le joueur tourne d’1/4 de tour dans le sens horaire TOUS les plateaux Lieux (d’un seul tenant) ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Horloge : quelle perte de temps ! ; l’Horloge avance. S’il n’y a plus de Traquenard disponible, on mélange soigneusement la défausse pour reconstituer la pile de Traquenards. == Capacités spéciales == Chaque Enquêteur dispose d’une Capacité spéciale utilisable à son tour : • Lucile Finemouche : TENACE Relancez une fois le dé Enquête si le résultat ne vous convient pas. Le nouveau résultat doit être appliqué. • Le Balafré : IMPLACCABLE Subissez les effets atténués d’un Traquenard : ne lancez qu’1 seul cube Hercule et ne fermez jamais les yeux face aux Yeux du démon ou au Vortex. • Allison Holmes : INDISCRÈTE Avant de dévoiler vos tuiles, regardez secrètement 1 tuile de votre choix. • Zacahire White : FOUINEUR Avant de dévoiler vos tuiles, regardez secrètement 2 tuiles porteuses d’un Indice ou d’un cube Hercule de votre choix. == Cartes 3ID == Si un joueur a écarté un Suspect à l’Agence 3ID en dévoilant une paire, il pioche 1 carte 3ID : • Les Objets peuvent être utilisées ultérieurement ; un Objet est placé à côté de la fiche Enquêteur du joueur puis défaussé une fois utilisé ; un joueur ne peut posséder qu’un seul Objet ; un Objet en surplus doit être donné à un autre joueur ou défaussé ; • Les Calepins permettent au joueur de prendre un cube Indice supplémentaire à sa couleur ; s’il n’en a plus de disponible, un autre joueur peut prendre un cube Indice supplémentaire à sa couleur ; s’il n’y a plus de cube Indice disponible, la carte est sans effet ; puis la carte est défaussée ; • Les Debriefings permettent au joueur, avant 3 heures, de prendre un cube Indice supplémentaire à sa couleur (comme un Calepin) ; à 3 heures et au-delà, ils permettent de retourner faces visibles toutes les tuiles porteuses d’Indice (les Indices retournent dans la réserve de leur Enquêteur) ; si des paires sont visibles, elles sont immédiatement placées à l’Agence 3ID (en ce cas, on ne pioche pas de carte 3ID et on n’ajoute pas de Traquenard) ; Si, au cours de la partie, la pioche de cartes 3ID est vide, on mélange soigneusement la défausse pour reconstituer la pioche. == Cartes Limbes == Si un joueur n’a pas dévoilé de paire, il pioche 1 carte Limbes : • Les Embûches ont un effet néfaste immédiat ; une fois l’effet d’une Embûche appliqué (ou si l’effet ne peut être appliqué), elle est défaussée ; à noter, certaines Embûches ne font effet qu’à partir de 3 heures ; • Les Malédictions ont un effet néfaste qui s’applique durant un tour de jeu complet ; la Malédiction est laissée face visible devant le joueur qui vient de la piocher ; elle est défaussée à la fin de son prochain tour ; plusieurs cartes Malédiction peuvent cumuler leurs effets. Si, au cours de la partie, la pioche de cartes Limbes est vide, l’Horloge avance et on mélange soigneusement la défausse pour reconstituer la pioche. == Coup de bluff == À partir de 6 heures et au-delà uniquement, à son tour, plutôt que de lancer le dé Enquête, un joueur peut tenter un Coup de bluff : il est intimement convaincu d’avoir découvert, par déduction ou par intuition, l’identité du démon des limbes... • Le joueur dévoile 1 tuile de son choix ; • Puis il dévoile la tuile Démon ; • Si les 2 tuiles sont strictement identiques, la partie est gagnée pour TOUS ; • Si les 2 tuiles sont différentes, la partie est perdue pour TOUS !!! == Fin de partie == Tous les joueurs perdent la partie si : • L’Horloge atteint l’heure des 3 ombres (à la 12ème heure) ; • Un joueur se trompe suite à un Coup de bluff. Tous les joueurs gagnent la partie si : • 13 Suspects ont été écartés à l’Agence 3ID ; • Un joueur réussit son Coup de bluff. Le dernier suspect est donc l’hôte du démon des limbes : les enquêteurs n’ont plus qu’à mener fissa le pauvre possédé au magasin de Mandrakologie pour qu’il y soit désenvoûté et l’esprit maléfique à jamais emprisonné dans une fiole magique d’Ozenbaum. == Descriptif des cartes 3ID == • Archéoscript : À votre tour, jouez 2 fois sans avoir à piocher de carte Limbes ou à ajouter de Traquenard. • Chronogyre : Placez un Indice disponible sur un Suspect que vous venez de dévoiler. Le Suspect est laissé visible jusqu’à ce que sa paire soit reconsituée. • Débriefing : Avant 3h, prenez un Indice à votre couleur. Après 3h, toutes les tuiles porteuses d’Indices sont dévoilées. Si une ou plusieurs paires sont visibles, elles sont placées à l’Agence 3ID. Retournez les autres tuiles faces cachées. • Calepin : Prenez un Indice disponible à votre couleur. S’il n’y en a plus, un autre joueur peut prendre un Indice à sa couleur. • Invertigo : Ignorez l’effet d’une carte Limbes qui vient d’être piochée. • Loupe analytique : Regardez secrètement une tuile de votre choix avant de dévoiler des tuiles. • Stylo traducteur : Relancez le dé Enquête si le résultat ne vous convient pas. Vous devez appliquer l’effet du nouveau résultat. • Révélateur d’empreinte : Écartez tous les cubes Hercule présents sur les Lieux vers le plateau Horloge. • Oreillettes à ultra-son : Regardez secrètement 2 tuiles porteuses d’Indices de votre choix avant de dévoiler des tuiles. == Descriptif des cartes Limbes == • Amnésie : Tous les Indices présents sur les Lieux sont rendus à leurs Enquêteurs. • Brouillard : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 tuile libre par Lieu et mélangez-les faces cachées puis diposez-en 1 par Lieu à des emplacements libres de votre choix. • Brume : Les joueurs n’ont pas le droit de laisser d’Indice sur les Lieux. • Confusion : Les joueurs ne peuvent pas se servir des Capacités spéciales de leurs Enquêteurs. • Fausse piste : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 paire de Suspects écartés à l’Agence 3ID et mélangez-les faces cachées avec 2 autres tuiles libres de votre choix puis disposez-en 1 par Lieu (si possible) à des emplacements libres de votre choix. • Hallucination : À son tour, un joueur doit intervertir la place des 2 tuiles qu’il vient de dévoiler. • Illusion : Avant 3h, rien ne se passe. À 3h et au-delà, lancez le dé Enquête jusqu’à tomber sur un Lieu et tournez le Lieu désigné d’1/4 de tour dans le sens horaire. • Manipulation : Avant 3h, rien ne se passe. À 3h et au-delà, intervertissez la place des 2 Lieux qui vous font face. • Paralysie : À son tour, un joueur ne peut dévoiler ses tuiles que sur un seul et unique Lieu. • Paranoïa : À son tour, un joueur regarde secrètement ses tuiles sans les montrer. Il peut toutefois les décrire et les dévoiler s’il tombe sur une paire de Suspect. Les Traquenards sont sans effet. • Réveil des ombres : Avant 3h, rien ne se passe. À 3h et au-delà, ajoutez un Traquenard disponible à un emplacement libre de votre choix. • Silence : Les joueurs n’ont pas le droit de parler. Ils peuvent toutefois faire des signes. • Temps accéléré : L’Horloge avance. • Ténèbres : Les joueurs doivent fermer les yeux. À son tour uniquement, un joueur peut ouvrir les yeux puis il doit les refermer dès que son tour est terminé. • Vortex : Avant 3h, rien ne se passe. À 3h et au-delà, tournez tous les Lieux (d’un seul tenant) d’1/4 de tour dans le sens horaire. 8b164c9aeb5052d99950b454f259766a55c3a395 1978 1977 2016-09-16T11:53:27Z Bigornot 14295 /* L'histoire */ wikitext text/x-wiki Coopératif • À partir de 8 ans • 2 à 4 joueurs • 30 minutes = L'histoire = Une ombre plane sur Ménilville : Elvyr Ozbaum, mandrakologue pourtant expérimenté, a libéré par inadvertance un démon des limbes. Ce mauvais génie s’est échappé et il est parvenu à se glisser dans l’esprit d’un des habitants du quartier. Depuis, il prend un malin plaisir à hypnotiser d’autres victimes innocentes afin de les pousser à faire n’importe quoi... Mais il y a plus inquiétant : s’il n’est pas chassé avant l’heure des 3 ombres, il prendra définitivement possession de son corps d’emprunt ! Voici un défi pour vous, intrépides enquêteurs de l’Agence 3ID : il vous faut au plus vite découvrir en qui se cache le démon des limbes avant qu’il ne dévore l’âme de sa victime et ne devienne à jamais son double maléfique. Mais avec le chat Hercule qui traîne dans vos pattes et le risque de vous faire envoûter à votre tour, la partie est loin d’être gagnée ! L'heure des 3 ombres est tiré de l'univers de Lucile Finemouche & Le Balafré, éditions Actes Sud Junior. == But du jeu == Sur le principe simple du Memory, il s’agit de reconstituer toutes les paires de personnages afin de déterminer celui dont le double n’est pas en jeu. Les joueurs incarnent des enquêteurs qui doivent coordonner leurs recherches dans Ménilville afin d’écarter un à un les suspects et ainsi débusquer le démon qui se cache parmi eux. Si l’horloge atteint l’heure des 3 ombres (12ème heure), la partie est perdue pour TOUS. Si 13 suspects sont écartés, le démon est démasqué et la partie est gagnée pour TOUS. == Tour de jeu == À son tour, un joueur doit lancer le dé Enquête puis appliquer son résultat. • Faces Réverbère / Chapeau / Pentacle / Rouage : le joueur dévoile 1 tuile du Lieu désigné par le dé et 1 tuile de son choix (du même Lieu ou d’un autre Lieu) ; si le Lieu désigné ne contient aucune tuile, le joueur ne peut dévoiler qu’1 seule tuile de son choix ; • Face Loupe : le joueur dévoile 2 tuiles de son choix ; • Face Horloge : l’Horloge avance puis le joueur dévoile 2 tuiles de son choix. ATTENTION : chaque Suspect existe en 2 versions (normale et hypnotisée), très proches visuellement l’une de l’autre . Il est donc très facile de les confondre ! Si le joueur dévoile 2 Suspects strictement identiques : • Il place les 2 tuiles en pile faces visibles à un emplacement libre du plateau Agence 3ID ; il parvient à innocenter un suspect et le mène illico à l’Agence afin qu’il y soit en sécurité ; • Il pioche une carte 3ID ; de retour au bureau, il récupère du matériel ; • Puis il prend, sans la regarder, 1 tuile Traquenard disponible et la place, face cachée, à un emplacement libre d’un Lieu de son choix ; durant l’absence de l’enquêteur, le démon en profite pour étendre son pouvoir sur Ménilville... Si le joueur dévoile 2 Suspects différents : • Il retourne les tuiles visibles faces cachées ; • Il peut, s’il le souhaite, y placer des Indices de sa réserve ; s’il n’a pas réussi à écarter de suspect, il a tout de même récolté quelques informations ; • Puis il pioche une carte Limbes ; le sort s’acharne ! Si le joueur dévoile 1 Traquenard : • S’il a dévoilé le Traquenard en premier, il en applique immédiatement l’effet sans dévoiler d’autre tuile ; • S’il a dévoilé le Traquenard en second, il retourne face cachée l’autre tuile Suspect qui a été dévoilée avant d’appliquer l’effet du Traquenard ; • Puis il défausse le Traquenard. Une fois son tour effectué, c’est au joueur à sa gauche de lancer le dé Enquête. == Indices == • S’il dévoile 2 Suspects différents, un joueur peut, s’il le souhaite, y laisser des Indices de sa réserve après les avoir retournés faces cachées ; une tuile ne peut accueillir qu’un seul Indice. • Un Indice placé sur une tuile sert simplement à marquer un Suspect, comme un pense-bête laissé en évidence : aux joueur de se souvenir de ce qu’il y a en dessous. • Si un joueur n’a plus d’Indice en réserve, il peut décider de déplacer ses Indices déjà présents sur les Lieux. • Quand une tuile porteuse d’un Indice est dévoilée, l’Indice retourne dans la réserve de son Enquêteur. • Quand une tuile porteuse d’un Indice est regardée secrètement, l’Indice reste sur la tuile. == Traquenards == Si le joueur dévoile 1 Traquenard, il doit en appliquer les effets : • Hercule : ce satané matou prend un malin plaisir à ralentir l’enquête ; le joueur jette 2 cubes Hercule vers le centre des 4 Lieux ; chaque cube Hercule est placé sur la tuile libre face cachée objectivement la plus proche ; une tuile porteuse d’un cube Hercule ne peut être ni regardée, ni dévoilée, ni mélangée ; à son tour, à la place de dévoiler 1 tuile, un joueur peut désigner 1 tuile porteuse d’un cube Hercule pour défausser le cube sans la dévoiler ; ainsi, la tuile est de nouveau accessible ; s’il n’y a plus de cubes Hercule disponibles, l’Horloge avance et le Traquenard est défaussé ; • Yeux du démon : le malheureux enquêteur croise le regard du démon, sa tête lui tourne et il s’évanouit ; le joueur tourne d’1/4 de tour dans le sens horaire le plateau Lieu de la couleur indiquée sur les Yeux du démon ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Vortex : l’enquêteur entrouvre une faille vers les limbes, la réalité en est toute chamboulée ; le joueur tourne d’1/4 de tour dans le sens horaire TOUS les plateaux Lieux (d’un seul tenant) ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Horloge : quelle perte de temps ! ; l’Horloge avance. S’il n’y a plus de Traquenard disponible, on mélange soigneusement la défausse pour reconstituer la pile de Traquenards. == Capacités spéciales == Chaque Enquêteur dispose d’une Capacité spéciale utilisable à son tour : • Lucile Finemouche : TENACE Relancez une fois le dé Enquête si le résultat ne vous convient pas. Le nouveau résultat doit être appliqué. • Le Balafré : IMPLACCABLE Subissez les effets atténués d’un Traquenard : ne lancez qu’1 seul cube Hercule et ne fermez jamais les yeux face aux Yeux du démon ou au Vortex. • Allison Holmes : INDISCRÈTE Avant de dévoiler vos tuiles, regardez secrètement 1 tuile de votre choix. • Zacahire White : FOUINEUR Avant de dévoiler vos tuiles, regardez secrètement 2 tuiles porteuses d’un Indice ou d’un cube Hercule de votre choix. == Cartes 3ID == Si un joueur a écarté un Suspect à l’Agence 3ID en dévoilant une paire, il pioche 1 carte 3ID : • Les Objets peuvent être utilisées ultérieurement ; un Objet est placé à côté de la fiche Enquêteur du joueur puis défaussé une fois utilisé ; un joueur ne peut posséder qu’un seul Objet ; un Objet en surplus doit être donné à un autre joueur ou défaussé ; • Les Calepins permettent au joueur de prendre un cube Indice supplémentaire à sa couleur ; s’il n’en a plus de disponible, un autre joueur peut prendre un cube Indice supplémentaire à sa couleur ; s’il n’y a plus de cube Indice disponible, la carte est sans effet ; puis la carte est défaussée ; • Les Debriefings permettent au joueur, avant 3 heures, de prendre un cube Indice supplémentaire à sa couleur (comme un Calepin) ; à 3 heures et au-delà, ils permettent de retourner faces visibles toutes les tuiles porteuses d’Indice (les Indices retournent dans la réserve de leur Enquêteur) ; si des paires sont visibles, elles sont immédiatement placées à l’Agence 3ID (en ce cas, on ne pioche pas de carte 3ID et on n’ajoute pas de Traquenard) ; Si, au cours de la partie, la pioche de cartes 3ID est vide, on mélange soigneusement la défausse pour reconstituer la pioche. == Cartes Limbes == Si un joueur n’a pas dévoilé de paire, il pioche 1 carte Limbes : • Les Embûches ont un effet néfaste immédiat ; une fois l’effet d’une Embûche appliqué (ou si l’effet ne peut être appliqué), elle est défaussée ; à noter, certaines Embûches ne font effet qu’à partir de 3 heures ; • Les Malédictions ont un effet néfaste qui s’applique durant un tour de jeu complet ; la Malédiction est laissée face visible devant le joueur qui vient de la piocher ; elle est défaussée à la fin de son prochain tour ; plusieurs cartes Malédiction peuvent cumuler leurs effets. Si, au cours de la partie, la pioche de cartes Limbes est vide, l’Horloge avance et on mélange soigneusement la défausse pour reconstituer la pioche. == Coup de bluff == À partir de 6 heures et au-delà uniquement, à son tour, plutôt que de lancer le dé Enquête, un joueur peut tenter un Coup de bluff : il est intimement convaincu d’avoir découvert, par déduction ou par intuition, l’identité du démon des limbes... • Le joueur dévoile 1 tuile de son choix ; • Puis il dévoile la tuile Démon ; • Si les 2 tuiles sont strictement identiques, la partie est gagnée pour TOUS ; • Si les 2 tuiles sont différentes, la partie est perdue pour TOUS !!! == Fin de partie == Tous les joueurs perdent la partie si : • L’Horloge atteint l’heure des 3 ombres (à la 12ème heure) ; • Un joueur se trompe suite à un Coup de bluff. Tous les joueurs gagnent la partie si : • 13 Suspects ont été écartés à l’Agence 3ID ; • Un joueur réussit son Coup de bluff. Le dernier suspect est donc l’hôte du démon des limbes : les enquêteurs n’ont plus qu’à mener fissa le pauvre possédé au magasin de Mandrakologie pour qu’il y soit désenvoûté et l’esprit maléfique à jamais emprisonné dans une fiole magique d’Ozenbaum. == Descriptif des cartes 3ID == • Archéoscript : À votre tour, jouez 2 fois sans avoir à piocher de carte Limbes ou à ajouter de Traquenard. • Chronogyre : Placez un Indice disponible sur un Suspect que vous venez de dévoiler. Le Suspect est laissé visible jusqu’à ce que sa paire soit reconsituée. • Débriefing : Avant 3h, prenez un Indice à votre couleur. Après 3h, toutes les tuiles porteuses d’Indices sont dévoilées. Si une ou plusieurs paires sont visibles, elles sont placées à l’Agence 3ID. Retournez les autres tuiles faces cachées. • Calepin : Prenez un Indice disponible à votre couleur. S’il n’y en a plus, un autre joueur peut prendre un Indice à sa couleur. • Invertigo : Ignorez l’effet d’une carte Limbes qui vient d’être piochée. • Loupe analytique : Regardez secrètement une tuile de votre choix avant de dévoiler des tuiles. • Stylo traducteur : Relancez le dé Enquête si le résultat ne vous convient pas. Vous devez appliquer l’effet du nouveau résultat. • Révélateur d’empreinte : Écartez tous les cubes Hercule présents sur les Lieux vers le plateau Horloge. • Oreillettes à ultra-son : Regardez secrètement 2 tuiles porteuses d’Indices de votre choix avant de dévoiler des tuiles. == Descriptif des cartes Limbes == • Amnésie : Tous les Indices présents sur les Lieux sont rendus à leurs Enquêteurs. • Brouillard : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 tuile libre par Lieu et mélangez-les faces cachées puis diposez-en 1 par Lieu à des emplacements libres de votre choix. • Brume : Les joueurs n’ont pas le droit de laisser d’Indice sur les Lieux. • Confusion : Les joueurs ne peuvent pas se servir des Capacités spéciales de leurs Enquêteurs. • Fausse piste : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 paire de Suspects écartés à l’Agence 3ID et mélangez-les faces cachées avec 2 autres tuiles libres de votre choix puis disposez-en 1 par Lieu (si possible) à des emplacements libres de votre choix. • Hallucination : À son tour, un joueur doit intervertir la place des 2 tuiles qu’il vient de dévoiler. • Illusion : Avant 3h, rien ne se passe. À 3h et au-delà, lancez le dé Enquête jusqu’à tomber sur un Lieu et tournez le Lieu désigné d’1/4 de tour dans le sens horaire. • Manipulation : Avant 3h, rien ne se passe. À 3h et au-delà, intervertissez la place des 2 Lieux qui vous font face. • Paralysie : À son tour, un joueur ne peut dévoiler ses tuiles que sur un seul et unique Lieu. • Paranoïa : À son tour, un joueur regarde secrètement ses tuiles sans les montrer. Il peut toutefois les décrire et les dévoiler s’il tombe sur une paire de Suspect. Les Traquenards sont sans effet. • Réveil des ombres : Avant 3h, rien ne se passe. À 3h et au-delà, ajoutez un Traquenard disponible à un emplacement libre de votre choix. • Silence : Les joueurs n’ont pas le droit de parler. Ils peuvent toutefois faire des signes. • Temps accéléré : L’Horloge avance. • Ténèbres : Les joueurs doivent fermer les yeux. À son tour uniquement, un joueur peut ouvrir les yeux puis il doit les refermer dès que son tour est terminé. • Vortex : Avant 3h, rien ne se passe. À 3h et au-delà, tournez tous les Lieux (d’un seul tenant) d’1/4 de tour dans le sens horaire. 1fba2a1d6920e15a3235814c71c42c20a770bd1d 1979 1978 2016-09-16T11:53:41Z Bigornot 14295 /* But du jeu */ wikitext text/x-wiki Coopératif • À partir de 8 ans • 2 à 4 joueurs • 30 minutes = L'histoire = Une ombre plane sur Ménilville : Elvyr Ozbaum, mandrakologue pourtant expérimenté, a libéré par inadvertance un démon des limbes. Ce mauvais génie s’est échappé et il est parvenu à se glisser dans l’esprit d’un des habitants du quartier. Depuis, il prend un malin plaisir à hypnotiser d’autres victimes innocentes afin de les pousser à faire n’importe quoi... Mais il y a plus inquiétant : s’il n’est pas chassé avant l’heure des 3 ombres, il prendra définitivement possession de son corps d’emprunt ! Voici un défi pour vous, intrépides enquêteurs de l’Agence 3ID : il vous faut au plus vite découvrir en qui se cache le démon des limbes avant qu’il ne dévore l’âme de sa victime et ne devienne à jamais son double maléfique. Mais avec le chat Hercule qui traîne dans vos pattes et le risque de vous faire envoûter à votre tour, la partie est loin d’être gagnée ! L'heure des 3 ombres est tiré de l'univers de Lucile Finemouche & Le Balafré, éditions Actes Sud Junior. == But du jeu == Sur le principe simple du Memory, il s’agit de reconstituer toutes les paires de personnages afin de déterminer celui dont le double n’est pas en jeu. Les joueurs incarnent des enquêteurs qui doivent coordonner leurs recherches dans Ménilville afin d’écarter un à un les suspects et ainsi débusquer le démon qui se cache parmi eux. Si l’horloge atteint l’heure des 3 ombres (12ème heure), la partie est perdue pour TOUS. Si 13 suspects sont écartés, le démon est démasqué et la partie est gagnée pour TOUS. == Tour de jeu == À son tour, un joueur doit lancer le dé Enquête puis appliquer son résultat. • Faces Réverbère / Chapeau / Pentacle / Rouage : le joueur dévoile 1 tuile du Lieu désigné par le dé et 1 tuile de son choix (du même Lieu ou d’un autre Lieu) ; si le Lieu désigné ne contient aucune tuile, le joueur ne peut dévoiler qu’1 seule tuile de son choix ; • Face Loupe : le joueur dévoile 2 tuiles de son choix ; • Face Horloge : l’Horloge avance puis le joueur dévoile 2 tuiles de son choix. ATTENTION : chaque Suspect existe en 2 versions (normale et hypnotisée), très proches visuellement l’une de l’autre . Il est donc très facile de les confondre ! Si le joueur dévoile 2 Suspects strictement identiques : • Il place les 2 tuiles en pile faces visibles à un emplacement libre du plateau Agence 3ID ; il parvient à innocenter un suspect et le mène illico à l’Agence afin qu’il y soit en sécurité ; • Il pioche une carte 3ID ; de retour au bureau, il récupère du matériel ; • Puis il prend, sans la regarder, 1 tuile Traquenard disponible et la place, face cachée, à un emplacement libre d’un Lieu de son choix ; durant l’absence de l’enquêteur, le démon en profite pour étendre son pouvoir sur Ménilville... Si le joueur dévoile 2 Suspects différents : • Il retourne les tuiles visibles faces cachées ; • Il peut, s’il le souhaite, y placer des Indices de sa réserve ; s’il n’a pas réussi à écarter de suspect, il a tout de même récolté quelques informations ; • Puis il pioche une carte Limbes ; le sort s’acharne ! Si le joueur dévoile 1 Traquenard : • S’il a dévoilé le Traquenard en premier, il en applique immédiatement l’effet sans dévoiler d’autre tuile ; • S’il a dévoilé le Traquenard en second, il retourne face cachée l’autre tuile Suspect qui a été dévoilée avant d’appliquer l’effet du Traquenard ; • Puis il défausse le Traquenard. Une fois son tour effectué, c’est au joueur à sa gauche de lancer le dé Enquête. == Indices == • S’il dévoile 2 Suspects différents, un joueur peut, s’il le souhaite, y laisser des Indices de sa réserve après les avoir retournés faces cachées ; une tuile ne peut accueillir qu’un seul Indice. • Un Indice placé sur une tuile sert simplement à marquer un Suspect, comme un pense-bête laissé en évidence : aux joueur de se souvenir de ce qu’il y a en dessous. • Si un joueur n’a plus d’Indice en réserve, il peut décider de déplacer ses Indices déjà présents sur les Lieux. • Quand une tuile porteuse d’un Indice est dévoilée, l’Indice retourne dans la réserve de son Enquêteur. • Quand une tuile porteuse d’un Indice est regardée secrètement, l’Indice reste sur la tuile. == Traquenards == Si le joueur dévoile 1 Traquenard, il doit en appliquer les effets : • Hercule : ce satané matou prend un malin plaisir à ralentir l’enquête ; le joueur jette 2 cubes Hercule vers le centre des 4 Lieux ; chaque cube Hercule est placé sur la tuile libre face cachée objectivement la plus proche ; une tuile porteuse d’un cube Hercule ne peut être ni regardée, ni dévoilée, ni mélangée ; à son tour, à la place de dévoiler 1 tuile, un joueur peut désigner 1 tuile porteuse d’un cube Hercule pour défausser le cube sans la dévoiler ; ainsi, la tuile est de nouveau accessible ; s’il n’y a plus de cubes Hercule disponibles, l’Horloge avance et le Traquenard est défaussé ; • Yeux du démon : le malheureux enquêteur croise le regard du démon, sa tête lui tourne et il s’évanouit ; le joueur tourne d’1/4 de tour dans le sens horaire le plateau Lieu de la couleur indiquée sur les Yeux du démon ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Vortex : l’enquêteur entrouvre une faille vers les limbes, la réalité en est toute chamboulée ; le joueur tourne d’1/4 de tour dans le sens horaire TOUS les plateaux Lieux (d’un seul tenant) ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Horloge : quelle perte de temps ! ; l’Horloge avance. S’il n’y a plus de Traquenard disponible, on mélange soigneusement la défausse pour reconstituer la pile de Traquenards. == Capacités spéciales == Chaque Enquêteur dispose d’une Capacité spéciale utilisable à son tour : • Lucile Finemouche : TENACE Relancez une fois le dé Enquête si le résultat ne vous convient pas. Le nouveau résultat doit être appliqué. • Le Balafré : IMPLACCABLE Subissez les effets atténués d’un Traquenard : ne lancez qu’1 seul cube Hercule et ne fermez jamais les yeux face aux Yeux du démon ou au Vortex. • Allison Holmes : INDISCRÈTE Avant de dévoiler vos tuiles, regardez secrètement 1 tuile de votre choix. • Zacahire White : FOUINEUR Avant de dévoiler vos tuiles, regardez secrètement 2 tuiles porteuses d’un Indice ou d’un cube Hercule de votre choix. == Cartes 3ID == Si un joueur a écarté un Suspect à l’Agence 3ID en dévoilant une paire, il pioche 1 carte 3ID : • Les Objets peuvent être utilisées ultérieurement ; un Objet est placé à côté de la fiche Enquêteur du joueur puis défaussé une fois utilisé ; un joueur ne peut posséder qu’un seul Objet ; un Objet en surplus doit être donné à un autre joueur ou défaussé ; • Les Calepins permettent au joueur de prendre un cube Indice supplémentaire à sa couleur ; s’il n’en a plus de disponible, un autre joueur peut prendre un cube Indice supplémentaire à sa couleur ; s’il n’y a plus de cube Indice disponible, la carte est sans effet ; puis la carte est défaussée ; • Les Debriefings permettent au joueur, avant 3 heures, de prendre un cube Indice supplémentaire à sa couleur (comme un Calepin) ; à 3 heures et au-delà, ils permettent de retourner faces visibles toutes les tuiles porteuses d’Indice (les Indices retournent dans la réserve de leur Enquêteur) ; si des paires sont visibles, elles sont immédiatement placées à l’Agence 3ID (en ce cas, on ne pioche pas de carte 3ID et on n’ajoute pas de Traquenard) ; Si, au cours de la partie, la pioche de cartes 3ID est vide, on mélange soigneusement la défausse pour reconstituer la pioche. == Cartes Limbes == Si un joueur n’a pas dévoilé de paire, il pioche 1 carte Limbes : • Les Embûches ont un effet néfaste immédiat ; une fois l’effet d’une Embûche appliqué (ou si l’effet ne peut être appliqué), elle est défaussée ; à noter, certaines Embûches ne font effet qu’à partir de 3 heures ; • Les Malédictions ont un effet néfaste qui s’applique durant un tour de jeu complet ; la Malédiction est laissée face visible devant le joueur qui vient de la piocher ; elle est défaussée à la fin de son prochain tour ; plusieurs cartes Malédiction peuvent cumuler leurs effets. Si, au cours de la partie, la pioche de cartes Limbes est vide, l’Horloge avance et on mélange soigneusement la défausse pour reconstituer la pioche. == Coup de bluff == À partir de 6 heures et au-delà uniquement, à son tour, plutôt que de lancer le dé Enquête, un joueur peut tenter un Coup de bluff : il est intimement convaincu d’avoir découvert, par déduction ou par intuition, l’identité du démon des limbes... • Le joueur dévoile 1 tuile de son choix ; • Puis il dévoile la tuile Démon ; • Si les 2 tuiles sont strictement identiques, la partie est gagnée pour TOUS ; • Si les 2 tuiles sont différentes, la partie est perdue pour TOUS !!! == Fin de partie == Tous les joueurs perdent la partie si : • L’Horloge atteint l’heure des 3 ombres (à la 12ème heure) ; • Un joueur se trompe suite à un Coup de bluff. Tous les joueurs gagnent la partie si : • 13 Suspects ont été écartés à l’Agence 3ID ; • Un joueur réussit son Coup de bluff. Le dernier suspect est donc l’hôte du démon des limbes : les enquêteurs n’ont plus qu’à mener fissa le pauvre possédé au magasin de Mandrakologie pour qu’il y soit désenvoûté et l’esprit maléfique à jamais emprisonné dans une fiole magique d’Ozenbaum. == Descriptif des cartes 3ID == • Archéoscript : À votre tour, jouez 2 fois sans avoir à piocher de carte Limbes ou à ajouter de Traquenard. • Chronogyre : Placez un Indice disponible sur un Suspect que vous venez de dévoiler. Le Suspect est laissé visible jusqu’à ce que sa paire soit reconsituée. • Débriefing : Avant 3h, prenez un Indice à votre couleur. Après 3h, toutes les tuiles porteuses d’Indices sont dévoilées. Si une ou plusieurs paires sont visibles, elles sont placées à l’Agence 3ID. Retournez les autres tuiles faces cachées. • Calepin : Prenez un Indice disponible à votre couleur. S’il n’y en a plus, un autre joueur peut prendre un Indice à sa couleur. • Invertigo : Ignorez l’effet d’une carte Limbes qui vient d’être piochée. • Loupe analytique : Regardez secrètement une tuile de votre choix avant de dévoiler des tuiles. • Stylo traducteur : Relancez le dé Enquête si le résultat ne vous convient pas. Vous devez appliquer l’effet du nouveau résultat. • Révélateur d’empreinte : Écartez tous les cubes Hercule présents sur les Lieux vers le plateau Horloge. • Oreillettes à ultra-son : Regardez secrètement 2 tuiles porteuses d’Indices de votre choix avant de dévoiler des tuiles. == Descriptif des cartes Limbes == • Amnésie : Tous les Indices présents sur les Lieux sont rendus à leurs Enquêteurs. • Brouillard : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 tuile libre par Lieu et mélangez-les faces cachées puis diposez-en 1 par Lieu à des emplacements libres de votre choix. • Brume : Les joueurs n’ont pas le droit de laisser d’Indice sur les Lieux. • Confusion : Les joueurs ne peuvent pas se servir des Capacités spéciales de leurs Enquêteurs. • Fausse piste : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 paire de Suspects écartés à l’Agence 3ID et mélangez-les faces cachées avec 2 autres tuiles libres de votre choix puis disposez-en 1 par Lieu (si possible) à des emplacements libres de votre choix. • Hallucination : À son tour, un joueur doit intervertir la place des 2 tuiles qu’il vient de dévoiler. • Illusion : Avant 3h, rien ne se passe. À 3h et au-delà, lancez le dé Enquête jusqu’à tomber sur un Lieu et tournez le Lieu désigné d’1/4 de tour dans le sens horaire. • Manipulation : Avant 3h, rien ne se passe. À 3h et au-delà, intervertissez la place des 2 Lieux qui vous font face. • Paralysie : À son tour, un joueur ne peut dévoiler ses tuiles que sur un seul et unique Lieu. • Paranoïa : À son tour, un joueur regarde secrètement ses tuiles sans les montrer. Il peut toutefois les décrire et les dévoiler s’il tombe sur une paire de Suspect. Les Traquenards sont sans effet. • Réveil des ombres : Avant 3h, rien ne se passe. À 3h et au-delà, ajoutez un Traquenard disponible à un emplacement libre de votre choix. • Silence : Les joueurs n’ont pas le droit de parler. Ils peuvent toutefois faire des signes. • Temps accéléré : L’Horloge avance. • Ténèbres : Les joueurs doivent fermer les yeux. À son tour uniquement, un joueur peut ouvrir les yeux puis il doit les refermer dès que son tour est terminé. • Vortex : Avant 3h, rien ne se passe. À 3h et au-delà, tournez tous les Lieux (d’un seul tenant) d’1/4 de tour dans le sens horaire. 633fdad3473b9189ad7157286f938df61154134f 1980 1979 2016-09-16T11:54:03Z Bigornot 14295 /* But du jeu */ wikitext text/x-wiki Coopératif • À partir de 8 ans • 2 à 4 joueurs • 30 minutes = L'histoire = Une ombre plane sur Ménilville : Elvyr Ozbaum, mandrakologue pourtant expérimenté, a libéré par inadvertance un démon des limbes. Ce mauvais génie s’est échappé et il est parvenu à se glisser dans l’esprit d’un des habitants du quartier. Depuis, il prend un malin plaisir à hypnotiser d’autres victimes innocentes afin de les pousser à faire n’importe quoi... Mais il y a plus inquiétant : s’il n’est pas chassé avant l’heure des 3 ombres, il prendra définitivement possession de son corps d’emprunt ! Voici un défi pour vous, intrépides enquêteurs de l’Agence 3ID : il vous faut au plus vite découvrir en qui se cache le démon des limbes avant qu’il ne dévore l’âme de sa victime et ne devienne à jamais son double maléfique. Mais avec le chat Hercule qui traîne dans vos pattes et le risque de vous faire envoûter à votre tour, la partie est loin d’être gagnée ! L'heure des 3 ombres est tiré de l'univers de Lucile Finemouche & Le Balafré, éditions Actes Sud Junior. = But du jeu = Sur le principe simple du Memory, il s’agit de reconstituer toutes les paires de personnages afin de déterminer celui dont le double n’est pas en jeu. Les joueurs incarnent des enquêteurs qui doivent coordonner leurs recherches dans Ménilville afin d’écarter un à un les suspects et ainsi débusquer le démon qui se cache parmi eux. Si l’horloge atteint l’heure des 3 ombres (12ème heure), la partie est perdue pour TOUS. Si 13 suspects sont écartés, le démon est démasqué et la partie est gagnée pour TOUS. == Tour de jeu == À son tour, un joueur doit lancer le dé Enquête puis appliquer son résultat. • Faces Réverbère / Chapeau / Pentacle / Rouage : le joueur dévoile 1 tuile du Lieu désigné par le dé et 1 tuile de son choix (du même Lieu ou d’un autre Lieu) ; si le Lieu désigné ne contient aucune tuile, le joueur ne peut dévoiler qu’1 seule tuile de son choix ; • Face Loupe : le joueur dévoile 2 tuiles de son choix ; • Face Horloge : l’Horloge avance puis le joueur dévoile 2 tuiles de son choix. ATTENTION : chaque Suspect existe en 2 versions (normale et hypnotisée), très proches visuellement l’une de l’autre . Il est donc très facile de les confondre ! Si le joueur dévoile 2 Suspects strictement identiques : • Il place les 2 tuiles en pile faces visibles à un emplacement libre du plateau Agence 3ID ; il parvient à innocenter un suspect et le mène illico à l’Agence afin qu’il y soit en sécurité ; • Il pioche une carte 3ID ; de retour au bureau, il récupère du matériel ; • Puis il prend, sans la regarder, 1 tuile Traquenard disponible et la place, face cachée, à un emplacement libre d’un Lieu de son choix ; durant l’absence de l’enquêteur, le démon en profite pour étendre son pouvoir sur Ménilville... Si le joueur dévoile 2 Suspects différents : • Il retourne les tuiles visibles faces cachées ; • Il peut, s’il le souhaite, y placer des Indices de sa réserve ; s’il n’a pas réussi à écarter de suspect, il a tout de même récolté quelques informations ; • Puis il pioche une carte Limbes ; le sort s’acharne ! Si le joueur dévoile 1 Traquenard : • S’il a dévoilé le Traquenard en premier, il en applique immédiatement l’effet sans dévoiler d’autre tuile ; • S’il a dévoilé le Traquenard en second, il retourne face cachée l’autre tuile Suspect qui a été dévoilée avant d’appliquer l’effet du Traquenard ; • Puis il défausse le Traquenard. Une fois son tour effectué, c’est au joueur à sa gauche de lancer le dé Enquête. == Indices == • S’il dévoile 2 Suspects différents, un joueur peut, s’il le souhaite, y laisser des Indices de sa réserve après les avoir retournés faces cachées ; une tuile ne peut accueillir qu’un seul Indice. • Un Indice placé sur une tuile sert simplement à marquer un Suspect, comme un pense-bête laissé en évidence : aux joueur de se souvenir de ce qu’il y a en dessous. • Si un joueur n’a plus d’Indice en réserve, il peut décider de déplacer ses Indices déjà présents sur les Lieux. • Quand une tuile porteuse d’un Indice est dévoilée, l’Indice retourne dans la réserve de son Enquêteur. • Quand une tuile porteuse d’un Indice est regardée secrètement, l’Indice reste sur la tuile. == Traquenards == Si le joueur dévoile 1 Traquenard, il doit en appliquer les effets : • Hercule : ce satané matou prend un malin plaisir à ralentir l’enquête ; le joueur jette 2 cubes Hercule vers le centre des 4 Lieux ; chaque cube Hercule est placé sur la tuile libre face cachée objectivement la plus proche ; une tuile porteuse d’un cube Hercule ne peut être ni regardée, ni dévoilée, ni mélangée ; à son tour, à la place de dévoiler 1 tuile, un joueur peut désigner 1 tuile porteuse d’un cube Hercule pour défausser le cube sans la dévoiler ; ainsi, la tuile est de nouveau accessible ; s’il n’y a plus de cubes Hercule disponibles, l’Horloge avance et le Traquenard est défaussé ; • Yeux du démon : le malheureux enquêteur croise le regard du démon, sa tête lui tourne et il s’évanouit ; le joueur tourne d’1/4 de tour dans le sens horaire le plateau Lieu de la couleur indiquée sur les Yeux du démon ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Vortex : l’enquêteur entrouvre une faille vers les limbes, la réalité en est toute chamboulée ; le joueur tourne d’1/4 de tour dans le sens horaire TOUS les plateaux Lieux (d’un seul tenant) ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Horloge : quelle perte de temps ! ; l’Horloge avance. S’il n’y a plus de Traquenard disponible, on mélange soigneusement la défausse pour reconstituer la pile de Traquenards. == Capacités spéciales == Chaque Enquêteur dispose d’une Capacité spéciale utilisable à son tour : • Lucile Finemouche : TENACE Relancez une fois le dé Enquête si le résultat ne vous convient pas. Le nouveau résultat doit être appliqué. • Le Balafré : IMPLACCABLE Subissez les effets atténués d’un Traquenard : ne lancez qu’1 seul cube Hercule et ne fermez jamais les yeux face aux Yeux du démon ou au Vortex. • Allison Holmes : INDISCRÈTE Avant de dévoiler vos tuiles, regardez secrètement 1 tuile de votre choix. • Zacahire White : FOUINEUR Avant de dévoiler vos tuiles, regardez secrètement 2 tuiles porteuses d’un Indice ou d’un cube Hercule de votre choix. == Cartes 3ID == Si un joueur a écarté un Suspect à l’Agence 3ID en dévoilant une paire, il pioche 1 carte 3ID : • Les Objets peuvent être utilisées ultérieurement ; un Objet est placé à côté de la fiche Enquêteur du joueur puis défaussé une fois utilisé ; un joueur ne peut posséder qu’un seul Objet ; un Objet en surplus doit être donné à un autre joueur ou défaussé ; • Les Calepins permettent au joueur de prendre un cube Indice supplémentaire à sa couleur ; s’il n’en a plus de disponible, un autre joueur peut prendre un cube Indice supplémentaire à sa couleur ; s’il n’y a plus de cube Indice disponible, la carte est sans effet ; puis la carte est défaussée ; • Les Debriefings permettent au joueur, avant 3 heures, de prendre un cube Indice supplémentaire à sa couleur (comme un Calepin) ; à 3 heures et au-delà, ils permettent de retourner faces visibles toutes les tuiles porteuses d’Indice (les Indices retournent dans la réserve de leur Enquêteur) ; si des paires sont visibles, elles sont immédiatement placées à l’Agence 3ID (en ce cas, on ne pioche pas de carte 3ID et on n’ajoute pas de Traquenard) ; Si, au cours de la partie, la pioche de cartes 3ID est vide, on mélange soigneusement la défausse pour reconstituer la pioche. == Cartes Limbes == Si un joueur n’a pas dévoilé de paire, il pioche 1 carte Limbes : • Les Embûches ont un effet néfaste immédiat ; une fois l’effet d’une Embûche appliqué (ou si l’effet ne peut être appliqué), elle est défaussée ; à noter, certaines Embûches ne font effet qu’à partir de 3 heures ; • Les Malédictions ont un effet néfaste qui s’applique durant un tour de jeu complet ; la Malédiction est laissée face visible devant le joueur qui vient de la piocher ; elle est défaussée à la fin de son prochain tour ; plusieurs cartes Malédiction peuvent cumuler leurs effets. Si, au cours de la partie, la pioche de cartes Limbes est vide, l’Horloge avance et on mélange soigneusement la défausse pour reconstituer la pioche. == Coup de bluff == À partir de 6 heures et au-delà uniquement, à son tour, plutôt que de lancer le dé Enquête, un joueur peut tenter un Coup de bluff : il est intimement convaincu d’avoir découvert, par déduction ou par intuition, l’identité du démon des limbes... • Le joueur dévoile 1 tuile de son choix ; • Puis il dévoile la tuile Démon ; • Si les 2 tuiles sont strictement identiques, la partie est gagnée pour TOUS ; • Si les 2 tuiles sont différentes, la partie est perdue pour TOUS !!! == Fin de partie == Tous les joueurs perdent la partie si : • L’Horloge atteint l’heure des 3 ombres (à la 12ème heure) ; • Un joueur se trompe suite à un Coup de bluff. Tous les joueurs gagnent la partie si : • 13 Suspects ont été écartés à l’Agence 3ID ; • Un joueur réussit son Coup de bluff. Le dernier suspect est donc l’hôte du démon des limbes : les enquêteurs n’ont plus qu’à mener fissa le pauvre possédé au magasin de Mandrakologie pour qu’il y soit désenvoûté et l’esprit maléfique à jamais emprisonné dans une fiole magique d’Ozenbaum. == Descriptif des cartes 3ID == • Archéoscript : À votre tour, jouez 2 fois sans avoir à piocher de carte Limbes ou à ajouter de Traquenard. • Chronogyre : Placez un Indice disponible sur un Suspect que vous venez de dévoiler. Le Suspect est laissé visible jusqu’à ce que sa paire soit reconsituée. • Débriefing : Avant 3h, prenez un Indice à votre couleur. Après 3h, toutes les tuiles porteuses d’Indices sont dévoilées. Si une ou plusieurs paires sont visibles, elles sont placées à l’Agence 3ID. Retournez les autres tuiles faces cachées. • Calepin : Prenez un Indice disponible à votre couleur. S’il n’y en a plus, un autre joueur peut prendre un Indice à sa couleur. • Invertigo : Ignorez l’effet d’une carte Limbes qui vient d’être piochée. • Loupe analytique : Regardez secrètement une tuile de votre choix avant de dévoiler des tuiles. • Stylo traducteur : Relancez le dé Enquête si le résultat ne vous convient pas. Vous devez appliquer l’effet du nouveau résultat. • Révélateur d’empreinte : Écartez tous les cubes Hercule présents sur les Lieux vers le plateau Horloge. • Oreillettes à ultra-son : Regardez secrètement 2 tuiles porteuses d’Indices de votre choix avant de dévoiler des tuiles. == Descriptif des cartes Limbes == • Amnésie : Tous les Indices présents sur les Lieux sont rendus à leurs Enquêteurs. • Brouillard : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 tuile libre par Lieu et mélangez-les faces cachées puis diposez-en 1 par Lieu à des emplacements libres de votre choix. • Brume : Les joueurs n’ont pas le droit de laisser d’Indice sur les Lieux. • Confusion : Les joueurs ne peuvent pas se servir des Capacités spéciales de leurs Enquêteurs. • Fausse piste : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 paire de Suspects écartés à l’Agence 3ID et mélangez-les faces cachées avec 2 autres tuiles libres de votre choix puis disposez-en 1 par Lieu (si possible) à des emplacements libres de votre choix. • Hallucination : À son tour, un joueur doit intervertir la place des 2 tuiles qu’il vient de dévoiler. • Illusion : Avant 3h, rien ne se passe. À 3h et au-delà, lancez le dé Enquête jusqu’à tomber sur un Lieu et tournez le Lieu désigné d’1/4 de tour dans le sens horaire. • Manipulation : Avant 3h, rien ne se passe. À 3h et au-delà, intervertissez la place des 2 Lieux qui vous font face. • Paralysie : À son tour, un joueur ne peut dévoiler ses tuiles que sur un seul et unique Lieu. • Paranoïa : À son tour, un joueur regarde secrètement ses tuiles sans les montrer. Il peut toutefois les décrire et les dévoiler s’il tombe sur une paire de Suspect. Les Traquenards sont sans effet. • Réveil des ombres : Avant 3h, rien ne se passe. À 3h et au-delà, ajoutez un Traquenard disponible à un emplacement libre de votre choix. • Silence : Les joueurs n’ont pas le droit de parler. Ils peuvent toutefois faire des signes. • Temps accéléré : L’Horloge avance. • Ténèbres : Les joueurs doivent fermer les yeux. À son tour uniquement, un joueur peut ouvrir les yeux puis il doit les refermer dès que son tour est terminé. • Vortex : Avant 3h, rien ne se passe. À 3h et au-delà, tournez tous les Lieux (d’un seul tenant) d’1/4 de tour dans le sens horaire. b362fcc1eeae666e45f75e000da118b5b6703dcf 1981 1980 2016-09-16T11:54:16Z Bigornot 14295 /* Tour de jeu */ wikitext text/x-wiki Coopératif • À partir de 8 ans • 2 à 4 joueurs • 30 minutes = L'histoire = Une ombre plane sur Ménilville : Elvyr Ozbaum, mandrakologue pourtant expérimenté, a libéré par inadvertance un démon des limbes. Ce mauvais génie s’est échappé et il est parvenu à se glisser dans l’esprit d’un des habitants du quartier. Depuis, il prend un malin plaisir à hypnotiser d’autres victimes innocentes afin de les pousser à faire n’importe quoi... Mais il y a plus inquiétant : s’il n’est pas chassé avant l’heure des 3 ombres, il prendra définitivement possession de son corps d’emprunt ! Voici un défi pour vous, intrépides enquêteurs de l’Agence 3ID : il vous faut au plus vite découvrir en qui se cache le démon des limbes avant qu’il ne dévore l’âme de sa victime et ne devienne à jamais son double maléfique. Mais avec le chat Hercule qui traîne dans vos pattes et le risque de vous faire envoûter à votre tour, la partie est loin d’être gagnée ! L'heure des 3 ombres est tiré de l'univers de Lucile Finemouche & Le Balafré, éditions Actes Sud Junior. = But du jeu = Sur le principe simple du Memory, il s’agit de reconstituer toutes les paires de personnages afin de déterminer celui dont le double n’est pas en jeu. Les joueurs incarnent des enquêteurs qui doivent coordonner leurs recherches dans Ménilville afin d’écarter un à un les suspects et ainsi débusquer le démon qui se cache parmi eux. Si l’horloge atteint l’heure des 3 ombres (12ème heure), la partie est perdue pour TOUS. Si 13 suspects sont écartés, le démon est démasqué et la partie est gagnée pour TOUS. = Tour de jeu = À son tour, un joueur doit lancer le dé Enquête puis appliquer son résultat. • Faces Réverbère / Chapeau / Pentacle / Rouage : le joueur dévoile 1 tuile du Lieu désigné par le dé et 1 tuile de son choix (du même Lieu ou d’un autre Lieu) ; si le Lieu désigné ne contient aucune tuile, le joueur ne peut dévoiler qu’1 seule tuile de son choix ; • Face Loupe : le joueur dévoile 2 tuiles de son choix ; • Face Horloge : l’Horloge avance puis le joueur dévoile 2 tuiles de son choix. ATTENTION : chaque Suspect existe en 2 versions (normale et hypnotisée), très proches visuellement l’une de l’autre . Il est donc très facile de les confondre ! Si le joueur dévoile 2 Suspects strictement identiques : • Il place les 2 tuiles en pile faces visibles à un emplacement libre du plateau Agence 3ID ; il parvient à innocenter un suspect et le mène illico à l’Agence afin qu’il y soit en sécurité ; • Il pioche une carte 3ID ; de retour au bureau, il récupère du matériel ; • Puis il prend, sans la regarder, 1 tuile Traquenard disponible et la place, face cachée, à un emplacement libre d’un Lieu de son choix ; durant l’absence de l’enquêteur, le démon en profite pour étendre son pouvoir sur Ménilville... Si le joueur dévoile 2 Suspects différents : • Il retourne les tuiles visibles faces cachées ; • Il peut, s’il le souhaite, y placer des Indices de sa réserve ; s’il n’a pas réussi à écarter de suspect, il a tout de même récolté quelques informations ; • Puis il pioche une carte Limbes ; le sort s’acharne ! Si le joueur dévoile 1 Traquenard : • S’il a dévoilé le Traquenard en premier, il en applique immédiatement l’effet sans dévoiler d’autre tuile ; • S’il a dévoilé le Traquenard en second, il retourne face cachée l’autre tuile Suspect qui a été dévoilée avant d’appliquer l’effet du Traquenard ; • Puis il défausse le Traquenard. Une fois son tour effectué, c’est au joueur à sa gauche de lancer le dé Enquête. == Indices == • S’il dévoile 2 Suspects différents, un joueur peut, s’il le souhaite, y laisser des Indices de sa réserve après les avoir retournés faces cachées ; une tuile ne peut accueillir qu’un seul Indice. • Un Indice placé sur une tuile sert simplement à marquer un Suspect, comme un pense-bête laissé en évidence : aux joueur de se souvenir de ce qu’il y a en dessous. • Si un joueur n’a plus d’Indice en réserve, il peut décider de déplacer ses Indices déjà présents sur les Lieux. • Quand une tuile porteuse d’un Indice est dévoilée, l’Indice retourne dans la réserve de son Enquêteur. • Quand une tuile porteuse d’un Indice est regardée secrètement, l’Indice reste sur la tuile. == Traquenards == Si le joueur dévoile 1 Traquenard, il doit en appliquer les effets : • Hercule : ce satané matou prend un malin plaisir à ralentir l’enquête ; le joueur jette 2 cubes Hercule vers le centre des 4 Lieux ; chaque cube Hercule est placé sur la tuile libre face cachée objectivement la plus proche ; une tuile porteuse d’un cube Hercule ne peut être ni regardée, ni dévoilée, ni mélangée ; à son tour, à la place de dévoiler 1 tuile, un joueur peut désigner 1 tuile porteuse d’un cube Hercule pour défausser le cube sans la dévoiler ; ainsi, la tuile est de nouveau accessible ; s’il n’y a plus de cubes Hercule disponibles, l’Horloge avance et le Traquenard est défaussé ; • Yeux du démon : le malheureux enquêteur croise le regard du démon, sa tête lui tourne et il s’évanouit ; le joueur tourne d’1/4 de tour dans le sens horaire le plateau Lieu de la couleur indiquée sur les Yeux du démon ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Vortex : l’enquêteur entrouvre une faille vers les limbes, la réalité en est toute chamboulée ; le joueur tourne d’1/4 de tour dans le sens horaire TOUS les plateaux Lieux (d’un seul tenant) ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Horloge : quelle perte de temps ! ; l’Horloge avance. S’il n’y a plus de Traquenard disponible, on mélange soigneusement la défausse pour reconstituer la pile de Traquenards. == Capacités spéciales == Chaque Enquêteur dispose d’une Capacité spéciale utilisable à son tour : • Lucile Finemouche : TENACE Relancez une fois le dé Enquête si le résultat ne vous convient pas. Le nouveau résultat doit être appliqué. • Le Balafré : IMPLACCABLE Subissez les effets atténués d’un Traquenard : ne lancez qu’1 seul cube Hercule et ne fermez jamais les yeux face aux Yeux du démon ou au Vortex. • Allison Holmes : INDISCRÈTE Avant de dévoiler vos tuiles, regardez secrètement 1 tuile de votre choix. • Zacahire White : FOUINEUR Avant de dévoiler vos tuiles, regardez secrètement 2 tuiles porteuses d’un Indice ou d’un cube Hercule de votre choix. == Cartes 3ID == Si un joueur a écarté un Suspect à l’Agence 3ID en dévoilant une paire, il pioche 1 carte 3ID : • Les Objets peuvent être utilisées ultérieurement ; un Objet est placé à côté de la fiche Enquêteur du joueur puis défaussé une fois utilisé ; un joueur ne peut posséder qu’un seul Objet ; un Objet en surplus doit être donné à un autre joueur ou défaussé ; • Les Calepins permettent au joueur de prendre un cube Indice supplémentaire à sa couleur ; s’il n’en a plus de disponible, un autre joueur peut prendre un cube Indice supplémentaire à sa couleur ; s’il n’y a plus de cube Indice disponible, la carte est sans effet ; puis la carte est défaussée ; • Les Debriefings permettent au joueur, avant 3 heures, de prendre un cube Indice supplémentaire à sa couleur (comme un Calepin) ; à 3 heures et au-delà, ils permettent de retourner faces visibles toutes les tuiles porteuses d’Indice (les Indices retournent dans la réserve de leur Enquêteur) ; si des paires sont visibles, elles sont immédiatement placées à l’Agence 3ID (en ce cas, on ne pioche pas de carte 3ID et on n’ajoute pas de Traquenard) ; Si, au cours de la partie, la pioche de cartes 3ID est vide, on mélange soigneusement la défausse pour reconstituer la pioche. == Cartes Limbes == Si un joueur n’a pas dévoilé de paire, il pioche 1 carte Limbes : • Les Embûches ont un effet néfaste immédiat ; une fois l’effet d’une Embûche appliqué (ou si l’effet ne peut être appliqué), elle est défaussée ; à noter, certaines Embûches ne font effet qu’à partir de 3 heures ; • Les Malédictions ont un effet néfaste qui s’applique durant un tour de jeu complet ; la Malédiction est laissée face visible devant le joueur qui vient de la piocher ; elle est défaussée à la fin de son prochain tour ; plusieurs cartes Malédiction peuvent cumuler leurs effets. Si, au cours de la partie, la pioche de cartes Limbes est vide, l’Horloge avance et on mélange soigneusement la défausse pour reconstituer la pioche. == Coup de bluff == À partir de 6 heures et au-delà uniquement, à son tour, plutôt que de lancer le dé Enquête, un joueur peut tenter un Coup de bluff : il est intimement convaincu d’avoir découvert, par déduction ou par intuition, l’identité du démon des limbes... • Le joueur dévoile 1 tuile de son choix ; • Puis il dévoile la tuile Démon ; • Si les 2 tuiles sont strictement identiques, la partie est gagnée pour TOUS ; • Si les 2 tuiles sont différentes, la partie est perdue pour TOUS !!! == Fin de partie == Tous les joueurs perdent la partie si : • L’Horloge atteint l’heure des 3 ombres (à la 12ème heure) ; • Un joueur se trompe suite à un Coup de bluff. Tous les joueurs gagnent la partie si : • 13 Suspects ont été écartés à l’Agence 3ID ; • Un joueur réussit son Coup de bluff. Le dernier suspect est donc l’hôte du démon des limbes : les enquêteurs n’ont plus qu’à mener fissa le pauvre possédé au magasin de Mandrakologie pour qu’il y soit désenvoûté et l’esprit maléfique à jamais emprisonné dans une fiole magique d’Ozenbaum. == Descriptif des cartes 3ID == • Archéoscript : À votre tour, jouez 2 fois sans avoir à piocher de carte Limbes ou à ajouter de Traquenard. • Chronogyre : Placez un Indice disponible sur un Suspect que vous venez de dévoiler. Le Suspect est laissé visible jusqu’à ce que sa paire soit reconsituée. • Débriefing : Avant 3h, prenez un Indice à votre couleur. Après 3h, toutes les tuiles porteuses d’Indices sont dévoilées. Si une ou plusieurs paires sont visibles, elles sont placées à l’Agence 3ID. Retournez les autres tuiles faces cachées. • Calepin : Prenez un Indice disponible à votre couleur. S’il n’y en a plus, un autre joueur peut prendre un Indice à sa couleur. • Invertigo : Ignorez l’effet d’une carte Limbes qui vient d’être piochée. • Loupe analytique : Regardez secrètement une tuile de votre choix avant de dévoiler des tuiles. • Stylo traducteur : Relancez le dé Enquête si le résultat ne vous convient pas. Vous devez appliquer l’effet du nouveau résultat. • Révélateur d’empreinte : Écartez tous les cubes Hercule présents sur les Lieux vers le plateau Horloge. • Oreillettes à ultra-son : Regardez secrètement 2 tuiles porteuses d’Indices de votre choix avant de dévoiler des tuiles. == Descriptif des cartes Limbes == • Amnésie : Tous les Indices présents sur les Lieux sont rendus à leurs Enquêteurs. • Brouillard : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 tuile libre par Lieu et mélangez-les faces cachées puis diposez-en 1 par Lieu à des emplacements libres de votre choix. • Brume : Les joueurs n’ont pas le droit de laisser d’Indice sur les Lieux. • Confusion : Les joueurs ne peuvent pas se servir des Capacités spéciales de leurs Enquêteurs. • Fausse piste : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 paire de Suspects écartés à l’Agence 3ID et mélangez-les faces cachées avec 2 autres tuiles libres de votre choix puis disposez-en 1 par Lieu (si possible) à des emplacements libres de votre choix. • Hallucination : À son tour, un joueur doit intervertir la place des 2 tuiles qu’il vient de dévoiler. • Illusion : Avant 3h, rien ne se passe. À 3h et au-delà, lancez le dé Enquête jusqu’à tomber sur un Lieu et tournez le Lieu désigné d’1/4 de tour dans le sens horaire. • Manipulation : Avant 3h, rien ne se passe. À 3h et au-delà, intervertissez la place des 2 Lieux qui vous font face. • Paralysie : À son tour, un joueur ne peut dévoiler ses tuiles que sur un seul et unique Lieu. • Paranoïa : À son tour, un joueur regarde secrètement ses tuiles sans les montrer. Il peut toutefois les décrire et les dévoiler s’il tombe sur une paire de Suspect. Les Traquenards sont sans effet. • Réveil des ombres : Avant 3h, rien ne se passe. À 3h et au-delà, ajoutez un Traquenard disponible à un emplacement libre de votre choix. • Silence : Les joueurs n’ont pas le droit de parler. Ils peuvent toutefois faire des signes. • Temps accéléré : L’Horloge avance. • Ténèbres : Les joueurs doivent fermer les yeux. À son tour uniquement, un joueur peut ouvrir les yeux puis il doit les refermer dès que son tour est terminé. • Vortex : Avant 3h, rien ne se passe. À 3h et au-delà, tournez tous les Lieux (d’un seul tenant) d’1/4 de tour dans le sens horaire. b8c698d60eec3481ea36bcc521ef490edc65c102 1982 1981 2016-09-16T11:54:43Z Bigornot 14295 /* Coup de bluff */ wikitext text/x-wiki Coopératif • À partir de 8 ans • 2 à 4 joueurs • 30 minutes = L'histoire = Une ombre plane sur Ménilville : Elvyr Ozbaum, mandrakologue pourtant expérimenté, a libéré par inadvertance un démon des limbes. Ce mauvais génie s’est échappé et il est parvenu à se glisser dans l’esprit d’un des habitants du quartier. Depuis, il prend un malin plaisir à hypnotiser d’autres victimes innocentes afin de les pousser à faire n’importe quoi... Mais il y a plus inquiétant : s’il n’est pas chassé avant l’heure des 3 ombres, il prendra définitivement possession de son corps d’emprunt ! Voici un défi pour vous, intrépides enquêteurs de l’Agence 3ID : il vous faut au plus vite découvrir en qui se cache le démon des limbes avant qu’il ne dévore l’âme de sa victime et ne devienne à jamais son double maléfique. Mais avec le chat Hercule qui traîne dans vos pattes et le risque de vous faire envoûter à votre tour, la partie est loin d’être gagnée ! L'heure des 3 ombres est tiré de l'univers de Lucile Finemouche & Le Balafré, éditions Actes Sud Junior. = But du jeu = Sur le principe simple du Memory, il s’agit de reconstituer toutes les paires de personnages afin de déterminer celui dont le double n’est pas en jeu. Les joueurs incarnent des enquêteurs qui doivent coordonner leurs recherches dans Ménilville afin d’écarter un à un les suspects et ainsi débusquer le démon qui se cache parmi eux. Si l’horloge atteint l’heure des 3 ombres (12ème heure), la partie est perdue pour TOUS. Si 13 suspects sont écartés, le démon est démasqué et la partie est gagnée pour TOUS. = Tour de jeu = À son tour, un joueur doit lancer le dé Enquête puis appliquer son résultat. • Faces Réverbère / Chapeau / Pentacle / Rouage : le joueur dévoile 1 tuile du Lieu désigné par le dé et 1 tuile de son choix (du même Lieu ou d’un autre Lieu) ; si le Lieu désigné ne contient aucune tuile, le joueur ne peut dévoiler qu’1 seule tuile de son choix ; • Face Loupe : le joueur dévoile 2 tuiles de son choix ; • Face Horloge : l’Horloge avance puis le joueur dévoile 2 tuiles de son choix. ATTENTION : chaque Suspect existe en 2 versions (normale et hypnotisée), très proches visuellement l’une de l’autre . Il est donc très facile de les confondre ! Si le joueur dévoile 2 Suspects strictement identiques : • Il place les 2 tuiles en pile faces visibles à un emplacement libre du plateau Agence 3ID ; il parvient à innocenter un suspect et le mène illico à l’Agence afin qu’il y soit en sécurité ; • Il pioche une carte 3ID ; de retour au bureau, il récupère du matériel ; • Puis il prend, sans la regarder, 1 tuile Traquenard disponible et la place, face cachée, à un emplacement libre d’un Lieu de son choix ; durant l’absence de l’enquêteur, le démon en profite pour étendre son pouvoir sur Ménilville... Si le joueur dévoile 2 Suspects différents : • Il retourne les tuiles visibles faces cachées ; • Il peut, s’il le souhaite, y placer des Indices de sa réserve ; s’il n’a pas réussi à écarter de suspect, il a tout de même récolté quelques informations ; • Puis il pioche une carte Limbes ; le sort s’acharne ! Si le joueur dévoile 1 Traquenard : • S’il a dévoilé le Traquenard en premier, il en applique immédiatement l’effet sans dévoiler d’autre tuile ; • S’il a dévoilé le Traquenard en second, il retourne face cachée l’autre tuile Suspect qui a été dévoilée avant d’appliquer l’effet du Traquenard ; • Puis il défausse le Traquenard. Une fois son tour effectué, c’est au joueur à sa gauche de lancer le dé Enquête. == Indices == • S’il dévoile 2 Suspects différents, un joueur peut, s’il le souhaite, y laisser des Indices de sa réserve après les avoir retournés faces cachées ; une tuile ne peut accueillir qu’un seul Indice. • Un Indice placé sur une tuile sert simplement à marquer un Suspect, comme un pense-bête laissé en évidence : aux joueur de se souvenir de ce qu’il y a en dessous. • Si un joueur n’a plus d’Indice en réserve, il peut décider de déplacer ses Indices déjà présents sur les Lieux. • Quand une tuile porteuse d’un Indice est dévoilée, l’Indice retourne dans la réserve de son Enquêteur. • Quand une tuile porteuse d’un Indice est regardée secrètement, l’Indice reste sur la tuile. == Traquenards == Si le joueur dévoile 1 Traquenard, il doit en appliquer les effets : • Hercule : ce satané matou prend un malin plaisir à ralentir l’enquête ; le joueur jette 2 cubes Hercule vers le centre des 4 Lieux ; chaque cube Hercule est placé sur la tuile libre face cachée objectivement la plus proche ; une tuile porteuse d’un cube Hercule ne peut être ni regardée, ni dévoilée, ni mélangée ; à son tour, à la place de dévoiler 1 tuile, un joueur peut désigner 1 tuile porteuse d’un cube Hercule pour défausser le cube sans la dévoiler ; ainsi, la tuile est de nouveau accessible ; s’il n’y a plus de cubes Hercule disponibles, l’Horloge avance et le Traquenard est défaussé ; • Yeux du démon : le malheureux enquêteur croise le regard du démon, sa tête lui tourne et il s’évanouit ; le joueur tourne d’1/4 de tour dans le sens horaire le plateau Lieu de la couleur indiquée sur les Yeux du démon ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Vortex : l’enquêteur entrouvre une faille vers les limbes, la réalité en est toute chamboulée ; le joueur tourne d’1/4 de tour dans le sens horaire TOUS les plateaux Lieux (d’un seul tenant) ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Horloge : quelle perte de temps ! ; l’Horloge avance. S’il n’y a plus de Traquenard disponible, on mélange soigneusement la défausse pour reconstituer la pile de Traquenards. == Capacités spéciales == Chaque Enquêteur dispose d’une Capacité spéciale utilisable à son tour : • Lucile Finemouche : TENACE Relancez une fois le dé Enquête si le résultat ne vous convient pas. Le nouveau résultat doit être appliqué. • Le Balafré : IMPLACCABLE Subissez les effets atténués d’un Traquenard : ne lancez qu’1 seul cube Hercule et ne fermez jamais les yeux face aux Yeux du démon ou au Vortex. • Allison Holmes : INDISCRÈTE Avant de dévoiler vos tuiles, regardez secrètement 1 tuile de votre choix. • Zacahire White : FOUINEUR Avant de dévoiler vos tuiles, regardez secrètement 2 tuiles porteuses d’un Indice ou d’un cube Hercule de votre choix. == Cartes 3ID == Si un joueur a écarté un Suspect à l’Agence 3ID en dévoilant une paire, il pioche 1 carte 3ID : • Les Objets peuvent être utilisées ultérieurement ; un Objet est placé à côté de la fiche Enquêteur du joueur puis défaussé une fois utilisé ; un joueur ne peut posséder qu’un seul Objet ; un Objet en surplus doit être donné à un autre joueur ou défaussé ; • Les Calepins permettent au joueur de prendre un cube Indice supplémentaire à sa couleur ; s’il n’en a plus de disponible, un autre joueur peut prendre un cube Indice supplémentaire à sa couleur ; s’il n’y a plus de cube Indice disponible, la carte est sans effet ; puis la carte est défaussée ; • Les Debriefings permettent au joueur, avant 3 heures, de prendre un cube Indice supplémentaire à sa couleur (comme un Calepin) ; à 3 heures et au-delà, ils permettent de retourner faces visibles toutes les tuiles porteuses d’Indice (les Indices retournent dans la réserve de leur Enquêteur) ; si des paires sont visibles, elles sont immédiatement placées à l’Agence 3ID (en ce cas, on ne pioche pas de carte 3ID et on n’ajoute pas de Traquenard) ; Si, au cours de la partie, la pioche de cartes 3ID est vide, on mélange soigneusement la défausse pour reconstituer la pioche. == Cartes Limbes == Si un joueur n’a pas dévoilé de paire, il pioche 1 carte Limbes : • Les Embûches ont un effet néfaste immédiat ; une fois l’effet d’une Embûche appliqué (ou si l’effet ne peut être appliqué), elle est défaussée ; à noter, certaines Embûches ne font effet qu’à partir de 3 heures ; • Les Malédictions ont un effet néfaste qui s’applique durant un tour de jeu complet ; la Malédiction est laissée face visible devant le joueur qui vient de la piocher ; elle est défaussée à la fin de son prochain tour ; plusieurs cartes Malédiction peuvent cumuler leurs effets. Si, au cours de la partie, la pioche de cartes Limbes est vide, l’Horloge avance et on mélange soigneusement la défausse pour reconstituer la pioche. = Coup de bluff = À partir de 6 heures et au-delà uniquement, à son tour, plutôt que de lancer le dé Enquête, un joueur peut tenter un Coup de bluff : il est intimement convaincu d’avoir découvert, par déduction ou par intuition, l’identité du démon des limbes... • Le joueur dévoile 1 tuile de son choix ; • Puis il dévoile la tuile Démon ; • Si les 2 tuiles sont strictement identiques, la partie est gagnée pour TOUS ; • Si les 2 tuiles sont différentes, la partie est perdue pour TOUS !!! == Fin de partie == Tous les joueurs perdent la partie si : • L’Horloge atteint l’heure des 3 ombres (à la 12ème heure) ; • Un joueur se trompe suite à un Coup de bluff. Tous les joueurs gagnent la partie si : • 13 Suspects ont été écartés à l’Agence 3ID ; • Un joueur réussit son Coup de bluff. Le dernier suspect est donc l’hôte du démon des limbes : les enquêteurs n’ont plus qu’à mener fissa le pauvre possédé au magasin de Mandrakologie pour qu’il y soit désenvoûté et l’esprit maléfique à jamais emprisonné dans une fiole magique d’Ozenbaum. == Descriptif des cartes 3ID == • Archéoscript : À votre tour, jouez 2 fois sans avoir à piocher de carte Limbes ou à ajouter de Traquenard. • Chronogyre : Placez un Indice disponible sur un Suspect que vous venez de dévoiler. Le Suspect est laissé visible jusqu’à ce que sa paire soit reconsituée. • Débriefing : Avant 3h, prenez un Indice à votre couleur. Après 3h, toutes les tuiles porteuses d’Indices sont dévoilées. Si une ou plusieurs paires sont visibles, elles sont placées à l’Agence 3ID. Retournez les autres tuiles faces cachées. • Calepin : Prenez un Indice disponible à votre couleur. S’il n’y en a plus, un autre joueur peut prendre un Indice à sa couleur. • Invertigo : Ignorez l’effet d’une carte Limbes qui vient d’être piochée. • Loupe analytique : Regardez secrètement une tuile de votre choix avant de dévoiler des tuiles. • Stylo traducteur : Relancez le dé Enquête si le résultat ne vous convient pas. Vous devez appliquer l’effet du nouveau résultat. • Révélateur d’empreinte : Écartez tous les cubes Hercule présents sur les Lieux vers le plateau Horloge. • Oreillettes à ultra-son : Regardez secrètement 2 tuiles porteuses d’Indices de votre choix avant de dévoiler des tuiles. == Descriptif des cartes Limbes == • Amnésie : Tous les Indices présents sur les Lieux sont rendus à leurs Enquêteurs. • Brouillard : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 tuile libre par Lieu et mélangez-les faces cachées puis diposez-en 1 par Lieu à des emplacements libres de votre choix. • Brume : Les joueurs n’ont pas le droit de laisser d’Indice sur les Lieux. • Confusion : Les joueurs ne peuvent pas se servir des Capacités spéciales de leurs Enquêteurs. • Fausse piste : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 paire de Suspects écartés à l’Agence 3ID et mélangez-les faces cachées avec 2 autres tuiles libres de votre choix puis disposez-en 1 par Lieu (si possible) à des emplacements libres de votre choix. • Hallucination : À son tour, un joueur doit intervertir la place des 2 tuiles qu’il vient de dévoiler. • Illusion : Avant 3h, rien ne se passe. À 3h et au-delà, lancez le dé Enquête jusqu’à tomber sur un Lieu et tournez le Lieu désigné d’1/4 de tour dans le sens horaire. • Manipulation : Avant 3h, rien ne se passe. À 3h et au-delà, intervertissez la place des 2 Lieux qui vous font face. • Paralysie : À son tour, un joueur ne peut dévoiler ses tuiles que sur un seul et unique Lieu. • Paranoïa : À son tour, un joueur regarde secrètement ses tuiles sans les montrer. Il peut toutefois les décrire et les dévoiler s’il tombe sur une paire de Suspect. Les Traquenards sont sans effet. • Réveil des ombres : Avant 3h, rien ne se passe. À 3h et au-delà, ajoutez un Traquenard disponible à un emplacement libre de votre choix. • Silence : Les joueurs n’ont pas le droit de parler. Ils peuvent toutefois faire des signes. • Temps accéléré : L’Horloge avance. • Ténèbres : Les joueurs doivent fermer les yeux. À son tour uniquement, un joueur peut ouvrir les yeux puis il doit les refermer dès que son tour est terminé. • Vortex : Avant 3h, rien ne se passe. À 3h et au-delà, tournez tous les Lieux (d’un seul tenant) d’1/4 de tour dans le sens horaire. 5009057a6b0d12a42d5920b04083a12badccd339 1983 1982 2016-09-16T11:54:52Z Bigornot 14295 /* Cartes 3ID */ wikitext text/x-wiki Coopératif • À partir de 8 ans • 2 à 4 joueurs • 30 minutes = L'histoire = Une ombre plane sur Ménilville : Elvyr Ozbaum, mandrakologue pourtant expérimenté, a libéré par inadvertance un démon des limbes. Ce mauvais génie s’est échappé et il est parvenu à se glisser dans l’esprit d’un des habitants du quartier. Depuis, il prend un malin plaisir à hypnotiser d’autres victimes innocentes afin de les pousser à faire n’importe quoi... Mais il y a plus inquiétant : s’il n’est pas chassé avant l’heure des 3 ombres, il prendra définitivement possession de son corps d’emprunt ! Voici un défi pour vous, intrépides enquêteurs de l’Agence 3ID : il vous faut au plus vite découvrir en qui se cache le démon des limbes avant qu’il ne dévore l’âme de sa victime et ne devienne à jamais son double maléfique. Mais avec le chat Hercule qui traîne dans vos pattes et le risque de vous faire envoûter à votre tour, la partie est loin d’être gagnée ! L'heure des 3 ombres est tiré de l'univers de Lucile Finemouche & Le Balafré, éditions Actes Sud Junior. = But du jeu = Sur le principe simple du Memory, il s’agit de reconstituer toutes les paires de personnages afin de déterminer celui dont le double n’est pas en jeu. Les joueurs incarnent des enquêteurs qui doivent coordonner leurs recherches dans Ménilville afin d’écarter un à un les suspects et ainsi débusquer le démon qui se cache parmi eux. Si l’horloge atteint l’heure des 3 ombres (12ème heure), la partie est perdue pour TOUS. Si 13 suspects sont écartés, le démon est démasqué et la partie est gagnée pour TOUS. = Tour de jeu = À son tour, un joueur doit lancer le dé Enquête puis appliquer son résultat. • Faces Réverbère / Chapeau / Pentacle / Rouage : le joueur dévoile 1 tuile du Lieu désigné par le dé et 1 tuile de son choix (du même Lieu ou d’un autre Lieu) ; si le Lieu désigné ne contient aucune tuile, le joueur ne peut dévoiler qu’1 seule tuile de son choix ; • Face Loupe : le joueur dévoile 2 tuiles de son choix ; • Face Horloge : l’Horloge avance puis le joueur dévoile 2 tuiles de son choix. ATTENTION : chaque Suspect existe en 2 versions (normale et hypnotisée), très proches visuellement l’une de l’autre . Il est donc très facile de les confondre ! Si le joueur dévoile 2 Suspects strictement identiques : • Il place les 2 tuiles en pile faces visibles à un emplacement libre du plateau Agence 3ID ; il parvient à innocenter un suspect et le mène illico à l’Agence afin qu’il y soit en sécurité ; • Il pioche une carte 3ID ; de retour au bureau, il récupère du matériel ; • Puis il prend, sans la regarder, 1 tuile Traquenard disponible et la place, face cachée, à un emplacement libre d’un Lieu de son choix ; durant l’absence de l’enquêteur, le démon en profite pour étendre son pouvoir sur Ménilville... Si le joueur dévoile 2 Suspects différents : • Il retourne les tuiles visibles faces cachées ; • Il peut, s’il le souhaite, y placer des Indices de sa réserve ; s’il n’a pas réussi à écarter de suspect, il a tout de même récolté quelques informations ; • Puis il pioche une carte Limbes ; le sort s’acharne ! Si le joueur dévoile 1 Traquenard : • S’il a dévoilé le Traquenard en premier, il en applique immédiatement l’effet sans dévoiler d’autre tuile ; • S’il a dévoilé le Traquenard en second, il retourne face cachée l’autre tuile Suspect qui a été dévoilée avant d’appliquer l’effet du Traquenard ; • Puis il défausse le Traquenard. Une fois son tour effectué, c’est au joueur à sa gauche de lancer le dé Enquête. == Indices == • S’il dévoile 2 Suspects différents, un joueur peut, s’il le souhaite, y laisser des Indices de sa réserve après les avoir retournés faces cachées ; une tuile ne peut accueillir qu’un seul Indice. • Un Indice placé sur une tuile sert simplement à marquer un Suspect, comme un pense-bête laissé en évidence : aux joueur de se souvenir de ce qu’il y a en dessous. • Si un joueur n’a plus d’Indice en réserve, il peut décider de déplacer ses Indices déjà présents sur les Lieux. • Quand une tuile porteuse d’un Indice est dévoilée, l’Indice retourne dans la réserve de son Enquêteur. • Quand une tuile porteuse d’un Indice est regardée secrètement, l’Indice reste sur la tuile. == Traquenards == Si le joueur dévoile 1 Traquenard, il doit en appliquer les effets : • Hercule : ce satané matou prend un malin plaisir à ralentir l’enquête ; le joueur jette 2 cubes Hercule vers le centre des 4 Lieux ; chaque cube Hercule est placé sur la tuile libre face cachée objectivement la plus proche ; une tuile porteuse d’un cube Hercule ne peut être ni regardée, ni dévoilée, ni mélangée ; à son tour, à la place de dévoiler 1 tuile, un joueur peut désigner 1 tuile porteuse d’un cube Hercule pour défausser le cube sans la dévoiler ; ainsi, la tuile est de nouveau accessible ; s’il n’y a plus de cubes Hercule disponibles, l’Horloge avance et le Traquenard est défaussé ; • Yeux du démon : le malheureux enquêteur croise le regard du démon, sa tête lui tourne et il s’évanouit ; le joueur tourne d’1/4 de tour dans le sens horaire le plateau Lieu de la couleur indiquée sur les Yeux du démon ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Vortex : l’enquêteur entrouvre une faille vers les limbes, la réalité en est toute chamboulée ; le joueur tourne d’1/4 de tour dans le sens horaire TOUS les plateaux Lieux (d’un seul tenant) ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Horloge : quelle perte de temps ! ; l’Horloge avance. S’il n’y a plus de Traquenard disponible, on mélange soigneusement la défausse pour reconstituer la pile de Traquenards. == Capacités spéciales == Chaque Enquêteur dispose d’une Capacité spéciale utilisable à son tour : • Lucile Finemouche : TENACE Relancez une fois le dé Enquête si le résultat ne vous convient pas. Le nouveau résultat doit être appliqué. • Le Balafré : IMPLACCABLE Subissez les effets atténués d’un Traquenard : ne lancez qu’1 seul cube Hercule et ne fermez jamais les yeux face aux Yeux du démon ou au Vortex. • Allison Holmes : INDISCRÈTE Avant de dévoiler vos tuiles, regardez secrètement 1 tuile de votre choix. • Zacahire White : FOUINEUR Avant de dévoiler vos tuiles, regardez secrètement 2 tuiles porteuses d’un Indice ou d’un cube Hercule de votre choix. == Cartes 3ID == Si un joueur a écarté un Suspect à l’Agence 3ID en dévoilant une paire, il pioche 1 carte 3ID : • Les Objets peuvent être utilisées ultérieurement ; un Objet est placé à côté de la fiche Enquêteur du joueur puis défaussé une fois utilisé ; un joueur ne peut posséder qu’un seul Objet ; un Objet en surplus doit être donné à un autre joueur ou défaussé ; • Les Calepins permettent au joueur de prendre un cube Indice supplémentaire à sa couleur ; s’il n’en a plus de disponible, un autre joueur peut prendre un cube Indice supplémentaire à sa couleur ; s’il n’y a plus de cube Indice disponible, la carte est sans effet ; puis la carte est défaussée ; • Les Debriefings permettent au joueur, avant 3 heures, de prendre un cube Indice supplémentaire à sa couleur (comme un Calepin) ; à 3 heures et au-delà, ils permettent de retourner faces visibles toutes les tuiles porteuses d’Indice (les Indices retournent dans la réserve de leur Enquêteur) ; si des paires sont visibles, elles sont immédiatement placées à l’Agence 3ID (en ce cas, on ne pioche pas de carte 3ID et on n’ajoute pas de Traquenard) ; Si, au cours de la partie, la pioche de cartes 3ID est vide, on mélange soigneusement la défausse pour reconstituer la pioche. == Cartes Limbes == Si un joueur n’a pas dévoilé de paire, il pioche 1 carte Limbes : • Les Embûches ont un effet néfaste immédiat ; une fois l’effet d’une Embûche appliqué (ou si l’effet ne peut être appliqué), elle est défaussée ; à noter, certaines Embûches ne font effet qu’à partir de 3 heures ; • Les Malédictions ont un effet néfaste qui s’applique durant un tour de jeu complet ; la Malédiction est laissée face visible devant le joueur qui vient de la piocher ; elle est défaussée à la fin de son prochain tour ; plusieurs cartes Malédiction peuvent cumuler leurs effets. Si, au cours de la partie, la pioche de cartes Limbes est vide, l’Horloge avance et on mélange soigneusement la défausse pour reconstituer la pioche. = Coup de bluff = À partir de 6 heures et au-delà uniquement, à son tour, plutôt que de lancer le dé Enquête, un joueur peut tenter un Coup de bluff : il est intimement convaincu d’avoir découvert, par déduction ou par intuition, l’identité du démon des limbes... • Le joueur dévoile 1 tuile de son choix ; • Puis il dévoile la tuile Démon ; • Si les 2 tuiles sont strictement identiques, la partie est gagnée pour TOUS ; • Si les 2 tuiles sont différentes, la partie est perdue pour TOUS !!! == Fin de partie == Tous les joueurs perdent la partie si : • L’Horloge atteint l’heure des 3 ombres (à la 12ème heure) ; • Un joueur se trompe suite à un Coup de bluff. Tous les joueurs gagnent la partie si : • 13 Suspects ont été écartés à l’Agence 3ID ; • Un joueur réussit son Coup de bluff. Le dernier suspect est donc l’hôte du démon des limbes : les enquêteurs n’ont plus qu’à mener fissa le pauvre possédé au magasin de Mandrakologie pour qu’il y soit désenvoûté et l’esprit maléfique à jamais emprisonné dans une fiole magique d’Ozenbaum. == Descriptif des cartes 3ID == • Archéoscript : À votre tour, jouez 2 fois sans avoir à piocher de carte Limbes ou à ajouter de Traquenard. • Chronogyre : Placez un Indice disponible sur un Suspect que vous venez de dévoiler. Le Suspect est laissé visible jusqu’à ce que sa paire soit reconsituée. • Débriefing : Avant 3h, prenez un Indice à votre couleur. Après 3h, toutes les tuiles porteuses d’Indices sont dévoilées. Si une ou plusieurs paires sont visibles, elles sont placées à l’Agence 3ID. Retournez les autres tuiles faces cachées. • Calepin : Prenez un Indice disponible à votre couleur. S’il n’y en a plus, un autre joueur peut prendre un Indice à sa couleur. • Invertigo : Ignorez l’effet d’une carte Limbes qui vient d’être piochée. • Loupe analytique : Regardez secrètement une tuile de votre choix avant de dévoiler des tuiles. • Stylo traducteur : Relancez le dé Enquête si le résultat ne vous convient pas. Vous devez appliquer l’effet du nouveau résultat. • Révélateur d’empreinte : Écartez tous les cubes Hercule présents sur les Lieux vers le plateau Horloge. • Oreillettes à ultra-son : Regardez secrètement 2 tuiles porteuses d’Indices de votre choix avant de dévoiler des tuiles. == Descriptif des cartes Limbes == • Amnésie : Tous les Indices présents sur les Lieux sont rendus à leurs Enquêteurs. • Brouillard : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 tuile libre par Lieu et mélangez-les faces cachées puis diposez-en 1 par Lieu à des emplacements libres de votre choix. • Brume : Les joueurs n’ont pas le droit de laisser d’Indice sur les Lieux. • Confusion : Les joueurs ne peuvent pas se servir des Capacités spéciales de leurs Enquêteurs. • Fausse piste : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 paire de Suspects écartés à l’Agence 3ID et mélangez-les faces cachées avec 2 autres tuiles libres de votre choix puis disposez-en 1 par Lieu (si possible) à des emplacements libres de votre choix. • Hallucination : À son tour, un joueur doit intervertir la place des 2 tuiles qu’il vient de dévoiler. • Illusion : Avant 3h, rien ne se passe. À 3h et au-delà, lancez le dé Enquête jusqu’à tomber sur un Lieu et tournez le Lieu désigné d’1/4 de tour dans le sens horaire. • Manipulation : Avant 3h, rien ne se passe. À 3h et au-delà, intervertissez la place des 2 Lieux qui vous font face. • Paralysie : À son tour, un joueur ne peut dévoiler ses tuiles que sur un seul et unique Lieu. • Paranoïa : À son tour, un joueur regarde secrètement ses tuiles sans les montrer. Il peut toutefois les décrire et les dévoiler s’il tombe sur une paire de Suspect. Les Traquenards sont sans effet. • Réveil des ombres : Avant 3h, rien ne se passe. À 3h et au-delà, ajoutez un Traquenard disponible à un emplacement libre de votre choix. • Silence : Les joueurs n’ont pas le droit de parler. Ils peuvent toutefois faire des signes. • Temps accéléré : L’Horloge avance. • Ténèbres : Les joueurs doivent fermer les yeux. À son tour uniquement, un joueur peut ouvrir les yeux puis il doit les refermer dès que son tour est terminé. • Vortex : Avant 3h, rien ne se passe. À 3h et au-delà, tournez tous les Lieux (d’un seul tenant) d’1/4 de tour dans le sens horaire. 9683976ef47258f81a75090e4e03aa987231594e 1984 1983 2016-09-16T11:55:07Z Bigornot 14295 /* Fin de partie */ wikitext text/x-wiki Coopératif • À partir de 8 ans • 2 à 4 joueurs • 30 minutes = L'histoire = Une ombre plane sur Ménilville : Elvyr Ozbaum, mandrakologue pourtant expérimenté, a libéré par inadvertance un démon des limbes. Ce mauvais génie s’est échappé et il est parvenu à se glisser dans l’esprit d’un des habitants du quartier. Depuis, il prend un malin plaisir à hypnotiser d’autres victimes innocentes afin de les pousser à faire n’importe quoi... Mais il y a plus inquiétant : s’il n’est pas chassé avant l’heure des 3 ombres, il prendra définitivement possession de son corps d’emprunt ! Voici un défi pour vous, intrépides enquêteurs de l’Agence 3ID : il vous faut au plus vite découvrir en qui se cache le démon des limbes avant qu’il ne dévore l’âme de sa victime et ne devienne à jamais son double maléfique. Mais avec le chat Hercule qui traîne dans vos pattes et le risque de vous faire envoûter à votre tour, la partie est loin d’être gagnée ! L'heure des 3 ombres est tiré de l'univers de Lucile Finemouche & Le Balafré, éditions Actes Sud Junior. = But du jeu = Sur le principe simple du Memory, il s’agit de reconstituer toutes les paires de personnages afin de déterminer celui dont le double n’est pas en jeu. Les joueurs incarnent des enquêteurs qui doivent coordonner leurs recherches dans Ménilville afin d’écarter un à un les suspects et ainsi débusquer le démon qui se cache parmi eux. Si l’horloge atteint l’heure des 3 ombres (12ème heure), la partie est perdue pour TOUS. Si 13 suspects sont écartés, le démon est démasqué et la partie est gagnée pour TOUS. = Tour de jeu = À son tour, un joueur doit lancer le dé Enquête puis appliquer son résultat. • Faces Réverbère / Chapeau / Pentacle / Rouage : le joueur dévoile 1 tuile du Lieu désigné par le dé et 1 tuile de son choix (du même Lieu ou d’un autre Lieu) ; si le Lieu désigné ne contient aucune tuile, le joueur ne peut dévoiler qu’1 seule tuile de son choix ; • Face Loupe : le joueur dévoile 2 tuiles de son choix ; • Face Horloge : l’Horloge avance puis le joueur dévoile 2 tuiles de son choix. ATTENTION : chaque Suspect existe en 2 versions (normale et hypnotisée), très proches visuellement l’une de l’autre . Il est donc très facile de les confondre ! Si le joueur dévoile 2 Suspects strictement identiques : • Il place les 2 tuiles en pile faces visibles à un emplacement libre du plateau Agence 3ID ; il parvient à innocenter un suspect et le mène illico à l’Agence afin qu’il y soit en sécurité ; • Il pioche une carte 3ID ; de retour au bureau, il récupère du matériel ; • Puis il prend, sans la regarder, 1 tuile Traquenard disponible et la place, face cachée, à un emplacement libre d’un Lieu de son choix ; durant l’absence de l’enquêteur, le démon en profite pour étendre son pouvoir sur Ménilville... Si le joueur dévoile 2 Suspects différents : • Il retourne les tuiles visibles faces cachées ; • Il peut, s’il le souhaite, y placer des Indices de sa réserve ; s’il n’a pas réussi à écarter de suspect, il a tout de même récolté quelques informations ; • Puis il pioche une carte Limbes ; le sort s’acharne ! Si le joueur dévoile 1 Traquenard : • S’il a dévoilé le Traquenard en premier, il en applique immédiatement l’effet sans dévoiler d’autre tuile ; • S’il a dévoilé le Traquenard en second, il retourne face cachée l’autre tuile Suspect qui a été dévoilée avant d’appliquer l’effet du Traquenard ; • Puis il défausse le Traquenard. Une fois son tour effectué, c’est au joueur à sa gauche de lancer le dé Enquête. == Indices == • S’il dévoile 2 Suspects différents, un joueur peut, s’il le souhaite, y laisser des Indices de sa réserve après les avoir retournés faces cachées ; une tuile ne peut accueillir qu’un seul Indice. • Un Indice placé sur une tuile sert simplement à marquer un Suspect, comme un pense-bête laissé en évidence : aux joueur de se souvenir de ce qu’il y a en dessous. • Si un joueur n’a plus d’Indice en réserve, il peut décider de déplacer ses Indices déjà présents sur les Lieux. • Quand une tuile porteuse d’un Indice est dévoilée, l’Indice retourne dans la réserve de son Enquêteur. • Quand une tuile porteuse d’un Indice est regardée secrètement, l’Indice reste sur la tuile. == Traquenards == Si le joueur dévoile 1 Traquenard, il doit en appliquer les effets : • Hercule : ce satané matou prend un malin plaisir à ralentir l’enquête ; le joueur jette 2 cubes Hercule vers le centre des 4 Lieux ; chaque cube Hercule est placé sur la tuile libre face cachée objectivement la plus proche ; une tuile porteuse d’un cube Hercule ne peut être ni regardée, ni dévoilée, ni mélangée ; à son tour, à la place de dévoiler 1 tuile, un joueur peut désigner 1 tuile porteuse d’un cube Hercule pour défausser le cube sans la dévoiler ; ainsi, la tuile est de nouveau accessible ; s’il n’y a plus de cubes Hercule disponibles, l’Horloge avance et le Traquenard est défaussé ; • Yeux du démon : le malheureux enquêteur croise le regard du démon, sa tête lui tourne et il s’évanouit ; le joueur tourne d’1/4 de tour dans le sens horaire le plateau Lieu de la couleur indiquée sur les Yeux du démon ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Vortex : l’enquêteur entrouvre une faille vers les limbes, la réalité en est toute chamboulée ; le joueur tourne d’1/4 de tour dans le sens horaire TOUS les plateaux Lieux (d’un seul tenant) ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Horloge : quelle perte de temps ! ; l’Horloge avance. S’il n’y a plus de Traquenard disponible, on mélange soigneusement la défausse pour reconstituer la pile de Traquenards. == Capacités spéciales == Chaque Enquêteur dispose d’une Capacité spéciale utilisable à son tour : • Lucile Finemouche : TENACE Relancez une fois le dé Enquête si le résultat ne vous convient pas. Le nouveau résultat doit être appliqué. • Le Balafré : IMPLACCABLE Subissez les effets atténués d’un Traquenard : ne lancez qu’1 seul cube Hercule et ne fermez jamais les yeux face aux Yeux du démon ou au Vortex. • Allison Holmes : INDISCRÈTE Avant de dévoiler vos tuiles, regardez secrètement 1 tuile de votre choix. • Zacahire White : FOUINEUR Avant de dévoiler vos tuiles, regardez secrètement 2 tuiles porteuses d’un Indice ou d’un cube Hercule de votre choix. == Cartes 3ID == Si un joueur a écarté un Suspect à l’Agence 3ID en dévoilant une paire, il pioche 1 carte 3ID : • Les Objets peuvent être utilisées ultérieurement ; un Objet est placé à côté de la fiche Enquêteur du joueur puis défaussé une fois utilisé ; un joueur ne peut posséder qu’un seul Objet ; un Objet en surplus doit être donné à un autre joueur ou défaussé ; • Les Calepins permettent au joueur de prendre un cube Indice supplémentaire à sa couleur ; s’il n’en a plus de disponible, un autre joueur peut prendre un cube Indice supplémentaire à sa couleur ; s’il n’y a plus de cube Indice disponible, la carte est sans effet ; puis la carte est défaussée ; • Les Debriefings permettent au joueur, avant 3 heures, de prendre un cube Indice supplémentaire à sa couleur (comme un Calepin) ; à 3 heures et au-delà, ils permettent de retourner faces visibles toutes les tuiles porteuses d’Indice (les Indices retournent dans la réserve de leur Enquêteur) ; si des paires sont visibles, elles sont immédiatement placées à l’Agence 3ID (en ce cas, on ne pioche pas de carte 3ID et on n’ajoute pas de Traquenard) ; Si, au cours de la partie, la pioche de cartes 3ID est vide, on mélange soigneusement la défausse pour reconstituer la pioche. == Cartes Limbes == Si un joueur n’a pas dévoilé de paire, il pioche 1 carte Limbes : • Les Embûches ont un effet néfaste immédiat ; une fois l’effet d’une Embûche appliqué (ou si l’effet ne peut être appliqué), elle est défaussée ; à noter, certaines Embûches ne font effet qu’à partir de 3 heures ; • Les Malédictions ont un effet néfaste qui s’applique durant un tour de jeu complet ; la Malédiction est laissée face visible devant le joueur qui vient de la piocher ; elle est défaussée à la fin de son prochain tour ; plusieurs cartes Malédiction peuvent cumuler leurs effets. Si, au cours de la partie, la pioche de cartes Limbes est vide, l’Horloge avance et on mélange soigneusement la défausse pour reconstituer la pioche. = Coup de bluff = À partir de 6 heures et au-delà uniquement, à son tour, plutôt que de lancer le dé Enquête, un joueur peut tenter un Coup de bluff : il est intimement convaincu d’avoir découvert, par déduction ou par intuition, l’identité du démon des limbes... • Le joueur dévoile 1 tuile de son choix ; • Puis il dévoile la tuile Démon ; • Si les 2 tuiles sont strictement identiques, la partie est gagnée pour TOUS ; • Si les 2 tuiles sont différentes, la partie est perdue pour TOUS !!! = Fin de partie = Tous les joueurs perdent la partie si : • L’Horloge atteint l’heure des 3 ombres (à la 12ème heure) ; • Un joueur se trompe suite à un Coup de bluff. Tous les joueurs gagnent la partie si : • 13 Suspects ont été écartés à l’Agence 3ID ; • Un joueur réussit son Coup de bluff. Le dernier suspect est donc l’hôte du démon des limbes : les enquêteurs n’ont plus qu’à mener fissa le pauvre possédé au magasin de Mandrakologie pour qu’il y soit désenvoûté et l’esprit maléfique à jamais emprisonné dans une fiole magique d’Ozenbaum. == Descriptif des cartes 3ID == • Archéoscript : À votre tour, jouez 2 fois sans avoir à piocher de carte Limbes ou à ajouter de Traquenard. • Chronogyre : Placez un Indice disponible sur un Suspect que vous venez de dévoiler. Le Suspect est laissé visible jusqu’à ce que sa paire soit reconsituée. • Débriefing : Avant 3h, prenez un Indice à votre couleur. Après 3h, toutes les tuiles porteuses d’Indices sont dévoilées. Si une ou plusieurs paires sont visibles, elles sont placées à l’Agence 3ID. Retournez les autres tuiles faces cachées. • Calepin : Prenez un Indice disponible à votre couleur. S’il n’y en a plus, un autre joueur peut prendre un Indice à sa couleur. • Invertigo : Ignorez l’effet d’une carte Limbes qui vient d’être piochée. • Loupe analytique : Regardez secrètement une tuile de votre choix avant de dévoiler des tuiles. • Stylo traducteur : Relancez le dé Enquête si le résultat ne vous convient pas. Vous devez appliquer l’effet du nouveau résultat. • Révélateur d’empreinte : Écartez tous les cubes Hercule présents sur les Lieux vers le plateau Horloge. • Oreillettes à ultra-son : Regardez secrètement 2 tuiles porteuses d’Indices de votre choix avant de dévoiler des tuiles. == Descriptif des cartes Limbes == • Amnésie : Tous les Indices présents sur les Lieux sont rendus à leurs Enquêteurs. • Brouillard : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 tuile libre par Lieu et mélangez-les faces cachées puis diposez-en 1 par Lieu à des emplacements libres de votre choix. • Brume : Les joueurs n’ont pas le droit de laisser d’Indice sur les Lieux. • Confusion : Les joueurs ne peuvent pas se servir des Capacités spéciales de leurs Enquêteurs. • Fausse piste : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 paire de Suspects écartés à l’Agence 3ID et mélangez-les faces cachées avec 2 autres tuiles libres de votre choix puis disposez-en 1 par Lieu (si possible) à des emplacements libres de votre choix. • Hallucination : À son tour, un joueur doit intervertir la place des 2 tuiles qu’il vient de dévoiler. • Illusion : Avant 3h, rien ne se passe. À 3h et au-delà, lancez le dé Enquête jusqu’à tomber sur un Lieu et tournez le Lieu désigné d’1/4 de tour dans le sens horaire. • Manipulation : Avant 3h, rien ne se passe. À 3h et au-delà, intervertissez la place des 2 Lieux qui vous font face. • Paralysie : À son tour, un joueur ne peut dévoiler ses tuiles que sur un seul et unique Lieu. • Paranoïa : À son tour, un joueur regarde secrètement ses tuiles sans les montrer. Il peut toutefois les décrire et les dévoiler s’il tombe sur une paire de Suspect. Les Traquenards sont sans effet. • Réveil des ombres : Avant 3h, rien ne se passe. À 3h et au-delà, ajoutez un Traquenard disponible à un emplacement libre de votre choix. • Silence : Les joueurs n’ont pas le droit de parler. Ils peuvent toutefois faire des signes. • Temps accéléré : L’Horloge avance. • Ténèbres : Les joueurs doivent fermer les yeux. À son tour uniquement, un joueur peut ouvrir les yeux puis il doit les refermer dès que son tour est terminé. • Vortex : Avant 3h, rien ne se passe. À 3h et au-delà, tournez tous les Lieux (d’un seul tenant) d’1/4 de tour dans le sens horaire. 0761595803da68a3ee05d03dde0abf3ef5d7ff77 1985 1984 2016-09-16T11:55:37Z Bigornot 14295 /* Descriptif des cartes 3ID */ wikitext text/x-wiki Coopératif • À partir de 8 ans • 2 à 4 joueurs • 30 minutes = L'histoire = Une ombre plane sur Ménilville : Elvyr Ozbaum, mandrakologue pourtant expérimenté, a libéré par inadvertance un démon des limbes. Ce mauvais génie s’est échappé et il est parvenu à se glisser dans l’esprit d’un des habitants du quartier. Depuis, il prend un malin plaisir à hypnotiser d’autres victimes innocentes afin de les pousser à faire n’importe quoi... Mais il y a plus inquiétant : s’il n’est pas chassé avant l’heure des 3 ombres, il prendra définitivement possession de son corps d’emprunt ! Voici un défi pour vous, intrépides enquêteurs de l’Agence 3ID : il vous faut au plus vite découvrir en qui se cache le démon des limbes avant qu’il ne dévore l’âme de sa victime et ne devienne à jamais son double maléfique. Mais avec le chat Hercule qui traîne dans vos pattes et le risque de vous faire envoûter à votre tour, la partie est loin d’être gagnée ! L'heure des 3 ombres est tiré de l'univers de Lucile Finemouche & Le Balafré, éditions Actes Sud Junior. = But du jeu = Sur le principe simple du Memory, il s’agit de reconstituer toutes les paires de personnages afin de déterminer celui dont le double n’est pas en jeu. Les joueurs incarnent des enquêteurs qui doivent coordonner leurs recherches dans Ménilville afin d’écarter un à un les suspects et ainsi débusquer le démon qui se cache parmi eux. Si l’horloge atteint l’heure des 3 ombres (12ème heure), la partie est perdue pour TOUS. Si 13 suspects sont écartés, le démon est démasqué et la partie est gagnée pour TOUS. = Tour de jeu = À son tour, un joueur doit lancer le dé Enquête puis appliquer son résultat. • Faces Réverbère / Chapeau / Pentacle / Rouage : le joueur dévoile 1 tuile du Lieu désigné par le dé et 1 tuile de son choix (du même Lieu ou d’un autre Lieu) ; si le Lieu désigné ne contient aucune tuile, le joueur ne peut dévoiler qu’1 seule tuile de son choix ; • Face Loupe : le joueur dévoile 2 tuiles de son choix ; • Face Horloge : l’Horloge avance puis le joueur dévoile 2 tuiles de son choix. ATTENTION : chaque Suspect existe en 2 versions (normale et hypnotisée), très proches visuellement l’une de l’autre . Il est donc très facile de les confondre ! Si le joueur dévoile 2 Suspects strictement identiques : • Il place les 2 tuiles en pile faces visibles à un emplacement libre du plateau Agence 3ID ; il parvient à innocenter un suspect et le mène illico à l’Agence afin qu’il y soit en sécurité ; • Il pioche une carte 3ID ; de retour au bureau, il récupère du matériel ; • Puis il prend, sans la regarder, 1 tuile Traquenard disponible et la place, face cachée, à un emplacement libre d’un Lieu de son choix ; durant l’absence de l’enquêteur, le démon en profite pour étendre son pouvoir sur Ménilville... Si le joueur dévoile 2 Suspects différents : • Il retourne les tuiles visibles faces cachées ; • Il peut, s’il le souhaite, y placer des Indices de sa réserve ; s’il n’a pas réussi à écarter de suspect, il a tout de même récolté quelques informations ; • Puis il pioche une carte Limbes ; le sort s’acharne ! Si le joueur dévoile 1 Traquenard : • S’il a dévoilé le Traquenard en premier, il en applique immédiatement l’effet sans dévoiler d’autre tuile ; • S’il a dévoilé le Traquenard en second, il retourne face cachée l’autre tuile Suspect qui a été dévoilée avant d’appliquer l’effet du Traquenard ; • Puis il défausse le Traquenard. Une fois son tour effectué, c’est au joueur à sa gauche de lancer le dé Enquête. == Indices == • S’il dévoile 2 Suspects différents, un joueur peut, s’il le souhaite, y laisser des Indices de sa réserve après les avoir retournés faces cachées ; une tuile ne peut accueillir qu’un seul Indice. • Un Indice placé sur une tuile sert simplement à marquer un Suspect, comme un pense-bête laissé en évidence : aux joueur de se souvenir de ce qu’il y a en dessous. • Si un joueur n’a plus d’Indice en réserve, il peut décider de déplacer ses Indices déjà présents sur les Lieux. • Quand une tuile porteuse d’un Indice est dévoilée, l’Indice retourne dans la réserve de son Enquêteur. • Quand une tuile porteuse d’un Indice est regardée secrètement, l’Indice reste sur la tuile. == Traquenards == Si le joueur dévoile 1 Traquenard, il doit en appliquer les effets : • Hercule : ce satané matou prend un malin plaisir à ralentir l’enquête ; le joueur jette 2 cubes Hercule vers le centre des 4 Lieux ; chaque cube Hercule est placé sur la tuile libre face cachée objectivement la plus proche ; une tuile porteuse d’un cube Hercule ne peut être ni regardée, ni dévoilée, ni mélangée ; à son tour, à la place de dévoiler 1 tuile, un joueur peut désigner 1 tuile porteuse d’un cube Hercule pour défausser le cube sans la dévoiler ; ainsi, la tuile est de nouveau accessible ; s’il n’y a plus de cubes Hercule disponibles, l’Horloge avance et le Traquenard est défaussé ; • Yeux du démon : le malheureux enquêteur croise le regard du démon, sa tête lui tourne et il s’évanouit ; le joueur tourne d’1/4 de tour dans le sens horaire le plateau Lieu de la couleur indiquée sur les Yeux du démon ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Vortex : l’enquêteur entrouvre une faille vers les limbes, la réalité en est toute chamboulée ; le joueur tourne d’1/4 de tour dans le sens horaire TOUS les plateaux Lieux (d’un seul tenant) ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Horloge : quelle perte de temps ! ; l’Horloge avance. S’il n’y a plus de Traquenard disponible, on mélange soigneusement la défausse pour reconstituer la pile de Traquenards. == Capacités spéciales == Chaque Enquêteur dispose d’une Capacité spéciale utilisable à son tour : • Lucile Finemouche : TENACE Relancez une fois le dé Enquête si le résultat ne vous convient pas. Le nouveau résultat doit être appliqué. • Le Balafré : IMPLACCABLE Subissez les effets atténués d’un Traquenard : ne lancez qu’1 seul cube Hercule et ne fermez jamais les yeux face aux Yeux du démon ou au Vortex. • Allison Holmes : INDISCRÈTE Avant de dévoiler vos tuiles, regardez secrètement 1 tuile de votre choix. • Zacahire White : FOUINEUR Avant de dévoiler vos tuiles, regardez secrètement 2 tuiles porteuses d’un Indice ou d’un cube Hercule de votre choix. == Cartes 3ID == Si un joueur a écarté un Suspect à l’Agence 3ID en dévoilant une paire, il pioche 1 carte 3ID : • Les Objets peuvent être utilisées ultérieurement ; un Objet est placé à côté de la fiche Enquêteur du joueur puis défaussé une fois utilisé ; un joueur ne peut posséder qu’un seul Objet ; un Objet en surplus doit être donné à un autre joueur ou défaussé ; • Les Calepins permettent au joueur de prendre un cube Indice supplémentaire à sa couleur ; s’il n’en a plus de disponible, un autre joueur peut prendre un cube Indice supplémentaire à sa couleur ; s’il n’y a plus de cube Indice disponible, la carte est sans effet ; puis la carte est défaussée ; • Les Debriefings permettent au joueur, avant 3 heures, de prendre un cube Indice supplémentaire à sa couleur (comme un Calepin) ; à 3 heures et au-delà, ils permettent de retourner faces visibles toutes les tuiles porteuses d’Indice (les Indices retournent dans la réserve de leur Enquêteur) ; si des paires sont visibles, elles sont immédiatement placées à l’Agence 3ID (en ce cas, on ne pioche pas de carte 3ID et on n’ajoute pas de Traquenard) ; Si, au cours de la partie, la pioche de cartes 3ID est vide, on mélange soigneusement la défausse pour reconstituer la pioche. == Cartes Limbes == Si un joueur n’a pas dévoilé de paire, il pioche 1 carte Limbes : • Les Embûches ont un effet néfaste immédiat ; une fois l’effet d’une Embûche appliqué (ou si l’effet ne peut être appliqué), elle est défaussée ; à noter, certaines Embûches ne font effet qu’à partir de 3 heures ; • Les Malédictions ont un effet néfaste qui s’applique durant un tour de jeu complet ; la Malédiction est laissée face visible devant le joueur qui vient de la piocher ; elle est défaussée à la fin de son prochain tour ; plusieurs cartes Malédiction peuvent cumuler leurs effets. Si, au cours de la partie, la pioche de cartes Limbes est vide, l’Horloge avance et on mélange soigneusement la défausse pour reconstituer la pioche. = Coup de bluff = À partir de 6 heures et au-delà uniquement, à son tour, plutôt que de lancer le dé Enquête, un joueur peut tenter un Coup de bluff : il est intimement convaincu d’avoir découvert, par déduction ou par intuition, l’identité du démon des limbes... • Le joueur dévoile 1 tuile de son choix ; • Puis il dévoile la tuile Démon ; • Si les 2 tuiles sont strictement identiques, la partie est gagnée pour TOUS ; • Si les 2 tuiles sont différentes, la partie est perdue pour TOUS !!! = Fin de partie = Tous les joueurs perdent la partie si : • L’Horloge atteint l’heure des 3 ombres (à la 12ème heure) ; • Un joueur se trompe suite à un Coup de bluff. Tous les joueurs gagnent la partie si : • 13 Suspects ont été écartés à l’Agence 3ID ; • Un joueur réussit son Coup de bluff. Le dernier suspect est donc l’hôte du démon des limbes : les enquêteurs n’ont plus qu’à mener fissa le pauvre possédé au magasin de Mandrakologie pour qu’il y soit désenvoûté et l’esprit maléfique à jamais emprisonné dans une fiole magique d’Ozenbaum. = Descriptif des cartes = == Cartes 3ID == • Archéoscript : À votre tour, jouez 2 fois sans avoir à piocher de carte Limbes ou à ajouter de Traquenard. • Chronogyre : Placez un Indice disponible sur un Suspect que vous venez de dévoiler. Le Suspect est laissé visible jusqu’à ce que sa paire soit reconsituée. • Débriefing : Avant 3h, prenez un Indice à votre couleur. Après 3h, toutes les tuiles porteuses d’Indices sont dévoilées. Si une ou plusieurs paires sont visibles, elles sont placées à l’Agence 3ID. Retournez les autres tuiles faces cachées. • Calepin : Prenez un Indice disponible à votre couleur. S’il n’y en a plus, un autre joueur peut prendre un Indice à sa couleur. • Invertigo : Ignorez l’effet d’une carte Limbes qui vient d’être piochée. • Loupe analytique : Regardez secrètement une tuile de votre choix avant de dévoiler des tuiles. • Stylo traducteur : Relancez le dé Enquête si le résultat ne vous convient pas. Vous devez appliquer l’effet du nouveau résultat. • Révélateur d’empreinte : Écartez tous les cubes Hercule présents sur les Lieux vers le plateau Horloge. • Oreillettes à ultra-son : Regardez secrètement 2 tuiles porteuses d’Indices de votre choix avant de dévoiler des tuiles. == Descriptif des cartes Limbes == • Amnésie : Tous les Indices présents sur les Lieux sont rendus à leurs Enquêteurs. • Brouillard : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 tuile libre par Lieu et mélangez-les faces cachées puis diposez-en 1 par Lieu à des emplacements libres de votre choix. • Brume : Les joueurs n’ont pas le droit de laisser d’Indice sur les Lieux. • Confusion : Les joueurs ne peuvent pas se servir des Capacités spéciales de leurs Enquêteurs. • Fausse piste : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 paire de Suspects écartés à l’Agence 3ID et mélangez-les faces cachées avec 2 autres tuiles libres de votre choix puis disposez-en 1 par Lieu (si possible) à des emplacements libres de votre choix. • Hallucination : À son tour, un joueur doit intervertir la place des 2 tuiles qu’il vient de dévoiler. • Illusion : Avant 3h, rien ne se passe. À 3h et au-delà, lancez le dé Enquête jusqu’à tomber sur un Lieu et tournez le Lieu désigné d’1/4 de tour dans le sens horaire. • Manipulation : Avant 3h, rien ne se passe. À 3h et au-delà, intervertissez la place des 2 Lieux qui vous font face. • Paralysie : À son tour, un joueur ne peut dévoiler ses tuiles que sur un seul et unique Lieu. • Paranoïa : À son tour, un joueur regarde secrètement ses tuiles sans les montrer. Il peut toutefois les décrire et les dévoiler s’il tombe sur une paire de Suspect. Les Traquenards sont sans effet. • Réveil des ombres : Avant 3h, rien ne se passe. À 3h et au-delà, ajoutez un Traquenard disponible à un emplacement libre de votre choix. • Silence : Les joueurs n’ont pas le droit de parler. Ils peuvent toutefois faire des signes. • Temps accéléré : L’Horloge avance. • Ténèbres : Les joueurs doivent fermer les yeux. À son tour uniquement, un joueur peut ouvrir les yeux puis il doit les refermer dès que son tour est terminé. • Vortex : Avant 3h, rien ne se passe. À 3h et au-delà, tournez tous les Lieux (d’un seul tenant) d’1/4 de tour dans le sens horaire. 243bade7550a255236b77cf9933c0b2e8e05e3be 1986 1985 2016-09-16T11:55:46Z Bigornot 14295 /* Descriptif des cartes Limbes */ wikitext text/x-wiki Coopératif • À partir de 8 ans • 2 à 4 joueurs • 30 minutes = L'histoire = Une ombre plane sur Ménilville : Elvyr Ozbaum, mandrakologue pourtant expérimenté, a libéré par inadvertance un démon des limbes. Ce mauvais génie s’est échappé et il est parvenu à se glisser dans l’esprit d’un des habitants du quartier. Depuis, il prend un malin plaisir à hypnotiser d’autres victimes innocentes afin de les pousser à faire n’importe quoi... Mais il y a plus inquiétant : s’il n’est pas chassé avant l’heure des 3 ombres, il prendra définitivement possession de son corps d’emprunt ! Voici un défi pour vous, intrépides enquêteurs de l’Agence 3ID : il vous faut au plus vite découvrir en qui se cache le démon des limbes avant qu’il ne dévore l’âme de sa victime et ne devienne à jamais son double maléfique. Mais avec le chat Hercule qui traîne dans vos pattes et le risque de vous faire envoûter à votre tour, la partie est loin d’être gagnée ! L'heure des 3 ombres est tiré de l'univers de Lucile Finemouche & Le Balafré, éditions Actes Sud Junior. = But du jeu = Sur le principe simple du Memory, il s’agit de reconstituer toutes les paires de personnages afin de déterminer celui dont le double n’est pas en jeu. Les joueurs incarnent des enquêteurs qui doivent coordonner leurs recherches dans Ménilville afin d’écarter un à un les suspects et ainsi débusquer le démon qui se cache parmi eux. Si l’horloge atteint l’heure des 3 ombres (12ème heure), la partie est perdue pour TOUS. Si 13 suspects sont écartés, le démon est démasqué et la partie est gagnée pour TOUS. = Tour de jeu = À son tour, un joueur doit lancer le dé Enquête puis appliquer son résultat. • Faces Réverbère / Chapeau / Pentacle / Rouage : le joueur dévoile 1 tuile du Lieu désigné par le dé et 1 tuile de son choix (du même Lieu ou d’un autre Lieu) ; si le Lieu désigné ne contient aucune tuile, le joueur ne peut dévoiler qu’1 seule tuile de son choix ; • Face Loupe : le joueur dévoile 2 tuiles de son choix ; • Face Horloge : l’Horloge avance puis le joueur dévoile 2 tuiles de son choix. ATTENTION : chaque Suspect existe en 2 versions (normale et hypnotisée), très proches visuellement l’une de l’autre . Il est donc très facile de les confondre ! Si le joueur dévoile 2 Suspects strictement identiques : • Il place les 2 tuiles en pile faces visibles à un emplacement libre du plateau Agence 3ID ; il parvient à innocenter un suspect et le mène illico à l’Agence afin qu’il y soit en sécurité ; • Il pioche une carte 3ID ; de retour au bureau, il récupère du matériel ; • Puis il prend, sans la regarder, 1 tuile Traquenard disponible et la place, face cachée, à un emplacement libre d’un Lieu de son choix ; durant l’absence de l’enquêteur, le démon en profite pour étendre son pouvoir sur Ménilville... Si le joueur dévoile 2 Suspects différents : • Il retourne les tuiles visibles faces cachées ; • Il peut, s’il le souhaite, y placer des Indices de sa réserve ; s’il n’a pas réussi à écarter de suspect, il a tout de même récolté quelques informations ; • Puis il pioche une carte Limbes ; le sort s’acharne ! Si le joueur dévoile 1 Traquenard : • S’il a dévoilé le Traquenard en premier, il en applique immédiatement l’effet sans dévoiler d’autre tuile ; • S’il a dévoilé le Traquenard en second, il retourne face cachée l’autre tuile Suspect qui a été dévoilée avant d’appliquer l’effet du Traquenard ; • Puis il défausse le Traquenard. Une fois son tour effectué, c’est au joueur à sa gauche de lancer le dé Enquête. == Indices == • S’il dévoile 2 Suspects différents, un joueur peut, s’il le souhaite, y laisser des Indices de sa réserve après les avoir retournés faces cachées ; une tuile ne peut accueillir qu’un seul Indice. • Un Indice placé sur une tuile sert simplement à marquer un Suspect, comme un pense-bête laissé en évidence : aux joueur de se souvenir de ce qu’il y a en dessous. • Si un joueur n’a plus d’Indice en réserve, il peut décider de déplacer ses Indices déjà présents sur les Lieux. • Quand une tuile porteuse d’un Indice est dévoilée, l’Indice retourne dans la réserve de son Enquêteur. • Quand une tuile porteuse d’un Indice est regardée secrètement, l’Indice reste sur la tuile. == Traquenards == Si le joueur dévoile 1 Traquenard, il doit en appliquer les effets : • Hercule : ce satané matou prend un malin plaisir à ralentir l’enquête ; le joueur jette 2 cubes Hercule vers le centre des 4 Lieux ; chaque cube Hercule est placé sur la tuile libre face cachée objectivement la plus proche ; une tuile porteuse d’un cube Hercule ne peut être ni regardée, ni dévoilée, ni mélangée ; à son tour, à la place de dévoiler 1 tuile, un joueur peut désigner 1 tuile porteuse d’un cube Hercule pour défausser le cube sans la dévoiler ; ainsi, la tuile est de nouveau accessible ; s’il n’y a plus de cubes Hercule disponibles, l’Horloge avance et le Traquenard est défaussé ; • Yeux du démon : le malheureux enquêteur croise le regard du démon, sa tête lui tourne et il s’évanouit ; le joueur tourne d’1/4 de tour dans le sens horaire le plateau Lieu de la couleur indiquée sur les Yeux du démon ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Vortex : l’enquêteur entrouvre une faille vers les limbes, la réalité en est toute chamboulée ; le joueur tourne d’1/4 de tour dans le sens horaire TOUS les plateaux Lieux (d’un seul tenant) ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Horloge : quelle perte de temps ! ; l’Horloge avance. S’il n’y a plus de Traquenard disponible, on mélange soigneusement la défausse pour reconstituer la pile de Traquenards. == Capacités spéciales == Chaque Enquêteur dispose d’une Capacité spéciale utilisable à son tour : • Lucile Finemouche : TENACE Relancez une fois le dé Enquête si le résultat ne vous convient pas. Le nouveau résultat doit être appliqué. • Le Balafré : IMPLACCABLE Subissez les effets atténués d’un Traquenard : ne lancez qu’1 seul cube Hercule et ne fermez jamais les yeux face aux Yeux du démon ou au Vortex. • Allison Holmes : INDISCRÈTE Avant de dévoiler vos tuiles, regardez secrètement 1 tuile de votre choix. • Zacahire White : FOUINEUR Avant de dévoiler vos tuiles, regardez secrètement 2 tuiles porteuses d’un Indice ou d’un cube Hercule de votre choix. == Cartes 3ID == Si un joueur a écarté un Suspect à l’Agence 3ID en dévoilant une paire, il pioche 1 carte 3ID : • Les Objets peuvent être utilisées ultérieurement ; un Objet est placé à côté de la fiche Enquêteur du joueur puis défaussé une fois utilisé ; un joueur ne peut posséder qu’un seul Objet ; un Objet en surplus doit être donné à un autre joueur ou défaussé ; • Les Calepins permettent au joueur de prendre un cube Indice supplémentaire à sa couleur ; s’il n’en a plus de disponible, un autre joueur peut prendre un cube Indice supplémentaire à sa couleur ; s’il n’y a plus de cube Indice disponible, la carte est sans effet ; puis la carte est défaussée ; • Les Debriefings permettent au joueur, avant 3 heures, de prendre un cube Indice supplémentaire à sa couleur (comme un Calepin) ; à 3 heures et au-delà, ils permettent de retourner faces visibles toutes les tuiles porteuses d’Indice (les Indices retournent dans la réserve de leur Enquêteur) ; si des paires sont visibles, elles sont immédiatement placées à l’Agence 3ID (en ce cas, on ne pioche pas de carte 3ID et on n’ajoute pas de Traquenard) ; Si, au cours de la partie, la pioche de cartes 3ID est vide, on mélange soigneusement la défausse pour reconstituer la pioche. == Cartes Limbes == Si un joueur n’a pas dévoilé de paire, il pioche 1 carte Limbes : • Les Embûches ont un effet néfaste immédiat ; une fois l’effet d’une Embûche appliqué (ou si l’effet ne peut être appliqué), elle est défaussée ; à noter, certaines Embûches ne font effet qu’à partir de 3 heures ; • Les Malédictions ont un effet néfaste qui s’applique durant un tour de jeu complet ; la Malédiction est laissée face visible devant le joueur qui vient de la piocher ; elle est défaussée à la fin de son prochain tour ; plusieurs cartes Malédiction peuvent cumuler leurs effets. Si, au cours de la partie, la pioche de cartes Limbes est vide, l’Horloge avance et on mélange soigneusement la défausse pour reconstituer la pioche. = Coup de bluff = À partir de 6 heures et au-delà uniquement, à son tour, plutôt que de lancer le dé Enquête, un joueur peut tenter un Coup de bluff : il est intimement convaincu d’avoir découvert, par déduction ou par intuition, l’identité du démon des limbes... • Le joueur dévoile 1 tuile de son choix ; • Puis il dévoile la tuile Démon ; • Si les 2 tuiles sont strictement identiques, la partie est gagnée pour TOUS ; • Si les 2 tuiles sont différentes, la partie est perdue pour TOUS !!! = Fin de partie = Tous les joueurs perdent la partie si : • L’Horloge atteint l’heure des 3 ombres (à la 12ème heure) ; • Un joueur se trompe suite à un Coup de bluff. Tous les joueurs gagnent la partie si : • 13 Suspects ont été écartés à l’Agence 3ID ; • Un joueur réussit son Coup de bluff. Le dernier suspect est donc l’hôte du démon des limbes : les enquêteurs n’ont plus qu’à mener fissa le pauvre possédé au magasin de Mandrakologie pour qu’il y soit désenvoûté et l’esprit maléfique à jamais emprisonné dans une fiole magique d’Ozenbaum. = Descriptif des cartes = == Cartes 3ID == • Archéoscript : À votre tour, jouez 2 fois sans avoir à piocher de carte Limbes ou à ajouter de Traquenard. • Chronogyre : Placez un Indice disponible sur un Suspect que vous venez de dévoiler. Le Suspect est laissé visible jusqu’à ce que sa paire soit reconsituée. • Débriefing : Avant 3h, prenez un Indice à votre couleur. Après 3h, toutes les tuiles porteuses d’Indices sont dévoilées. Si une ou plusieurs paires sont visibles, elles sont placées à l’Agence 3ID. Retournez les autres tuiles faces cachées. • Calepin : Prenez un Indice disponible à votre couleur. S’il n’y en a plus, un autre joueur peut prendre un Indice à sa couleur. • Invertigo : Ignorez l’effet d’une carte Limbes qui vient d’être piochée. • Loupe analytique : Regardez secrètement une tuile de votre choix avant de dévoiler des tuiles. • Stylo traducteur : Relancez le dé Enquête si le résultat ne vous convient pas. Vous devez appliquer l’effet du nouveau résultat. • Révélateur d’empreinte : Écartez tous les cubes Hercule présents sur les Lieux vers le plateau Horloge. • Oreillettes à ultra-son : Regardez secrètement 2 tuiles porteuses d’Indices de votre choix avant de dévoiler des tuiles. == Cartes Limbes == • Amnésie : Tous les Indices présents sur les Lieux sont rendus à leurs Enquêteurs. • Brouillard : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 tuile libre par Lieu et mélangez-les faces cachées puis diposez-en 1 par Lieu à des emplacements libres de votre choix. • Brume : Les joueurs n’ont pas le droit de laisser d’Indice sur les Lieux. • Confusion : Les joueurs ne peuvent pas se servir des Capacités spéciales de leurs Enquêteurs. • Fausse piste : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 paire de Suspects écartés à l’Agence 3ID et mélangez-les faces cachées avec 2 autres tuiles libres de votre choix puis disposez-en 1 par Lieu (si possible) à des emplacements libres de votre choix. • Hallucination : À son tour, un joueur doit intervertir la place des 2 tuiles qu’il vient de dévoiler. • Illusion : Avant 3h, rien ne se passe. À 3h et au-delà, lancez le dé Enquête jusqu’à tomber sur un Lieu et tournez le Lieu désigné d’1/4 de tour dans le sens horaire. • Manipulation : Avant 3h, rien ne se passe. À 3h et au-delà, intervertissez la place des 2 Lieux qui vous font face. • Paralysie : À son tour, un joueur ne peut dévoiler ses tuiles que sur un seul et unique Lieu. • Paranoïa : À son tour, un joueur regarde secrètement ses tuiles sans les montrer. Il peut toutefois les décrire et les dévoiler s’il tombe sur une paire de Suspect. Les Traquenards sont sans effet. • Réveil des ombres : Avant 3h, rien ne se passe. À 3h et au-delà, ajoutez un Traquenard disponible à un emplacement libre de votre choix. • Silence : Les joueurs n’ont pas le droit de parler. Ils peuvent toutefois faire des signes. • Temps accéléré : L’Horloge avance. • Ténèbres : Les joueurs doivent fermer les yeux. À son tour uniquement, un joueur peut ouvrir les yeux puis il doit les refermer dès que son tour est terminé. • Vortex : Avant 3h, rien ne se passe. À 3h et au-delà, tournez tous les Lieux (d’un seul tenant) d’1/4 de tour dans le sens horaire. 886c52c0c73253d45610f15705c6ea42082c2f2a 1987 1986 2016-09-16T11:56:43Z Bigornot 14295 /* Descriptif des cartes */ wikitext text/x-wiki Coopératif • À partir de 8 ans • 2 à 4 joueurs • 30 minutes = L'histoire = Une ombre plane sur Ménilville : Elvyr Ozbaum, mandrakologue pourtant expérimenté, a libéré par inadvertance un démon des limbes. Ce mauvais génie s’est échappé et il est parvenu à se glisser dans l’esprit d’un des habitants du quartier. Depuis, il prend un malin plaisir à hypnotiser d’autres victimes innocentes afin de les pousser à faire n’importe quoi... Mais il y a plus inquiétant : s’il n’est pas chassé avant l’heure des 3 ombres, il prendra définitivement possession de son corps d’emprunt ! Voici un défi pour vous, intrépides enquêteurs de l’Agence 3ID : il vous faut au plus vite découvrir en qui se cache le démon des limbes avant qu’il ne dévore l’âme de sa victime et ne devienne à jamais son double maléfique. Mais avec le chat Hercule qui traîne dans vos pattes et le risque de vous faire envoûter à votre tour, la partie est loin d’être gagnée ! L'heure des 3 ombres est tiré de l'univers de Lucile Finemouche & Le Balafré, éditions Actes Sud Junior. = But du jeu = Sur le principe simple du Memory, il s’agit de reconstituer toutes les paires de personnages afin de déterminer celui dont le double n’est pas en jeu. Les joueurs incarnent des enquêteurs qui doivent coordonner leurs recherches dans Ménilville afin d’écarter un à un les suspects et ainsi débusquer le démon qui se cache parmi eux. Si l’horloge atteint l’heure des 3 ombres (12ème heure), la partie est perdue pour TOUS. Si 13 suspects sont écartés, le démon est démasqué et la partie est gagnée pour TOUS. = Tour de jeu = À son tour, un joueur doit lancer le dé Enquête puis appliquer son résultat. • Faces Réverbère / Chapeau / Pentacle / Rouage : le joueur dévoile 1 tuile du Lieu désigné par le dé et 1 tuile de son choix (du même Lieu ou d’un autre Lieu) ; si le Lieu désigné ne contient aucune tuile, le joueur ne peut dévoiler qu’1 seule tuile de son choix ; • Face Loupe : le joueur dévoile 2 tuiles de son choix ; • Face Horloge : l’Horloge avance puis le joueur dévoile 2 tuiles de son choix. ATTENTION : chaque Suspect existe en 2 versions (normale et hypnotisée), très proches visuellement l’une de l’autre . Il est donc très facile de les confondre ! Si le joueur dévoile 2 Suspects strictement identiques : • Il place les 2 tuiles en pile faces visibles à un emplacement libre du plateau Agence 3ID ; il parvient à innocenter un suspect et le mène illico à l’Agence afin qu’il y soit en sécurité ; • Il pioche une carte 3ID ; de retour au bureau, il récupère du matériel ; • Puis il prend, sans la regarder, 1 tuile Traquenard disponible et la place, face cachée, à un emplacement libre d’un Lieu de son choix ; durant l’absence de l’enquêteur, le démon en profite pour étendre son pouvoir sur Ménilville... Si le joueur dévoile 2 Suspects différents : • Il retourne les tuiles visibles faces cachées ; • Il peut, s’il le souhaite, y placer des Indices de sa réserve ; s’il n’a pas réussi à écarter de suspect, il a tout de même récolté quelques informations ; • Puis il pioche une carte Limbes ; le sort s’acharne ! Si le joueur dévoile 1 Traquenard : • S’il a dévoilé le Traquenard en premier, il en applique immédiatement l’effet sans dévoiler d’autre tuile ; • S’il a dévoilé le Traquenard en second, il retourne face cachée l’autre tuile Suspect qui a été dévoilée avant d’appliquer l’effet du Traquenard ; • Puis il défausse le Traquenard. Une fois son tour effectué, c’est au joueur à sa gauche de lancer le dé Enquête. == Indices == • S’il dévoile 2 Suspects différents, un joueur peut, s’il le souhaite, y laisser des Indices de sa réserve après les avoir retournés faces cachées ; une tuile ne peut accueillir qu’un seul Indice. • Un Indice placé sur une tuile sert simplement à marquer un Suspect, comme un pense-bête laissé en évidence : aux joueur de se souvenir de ce qu’il y a en dessous. • Si un joueur n’a plus d’Indice en réserve, il peut décider de déplacer ses Indices déjà présents sur les Lieux. • Quand une tuile porteuse d’un Indice est dévoilée, l’Indice retourne dans la réserve de son Enquêteur. • Quand une tuile porteuse d’un Indice est regardée secrètement, l’Indice reste sur la tuile. == Traquenards == Si le joueur dévoile 1 Traquenard, il doit en appliquer les effets : • Hercule : ce satané matou prend un malin plaisir à ralentir l’enquête ; le joueur jette 2 cubes Hercule vers le centre des 4 Lieux ; chaque cube Hercule est placé sur la tuile libre face cachée objectivement la plus proche ; une tuile porteuse d’un cube Hercule ne peut être ni regardée, ni dévoilée, ni mélangée ; à son tour, à la place de dévoiler 1 tuile, un joueur peut désigner 1 tuile porteuse d’un cube Hercule pour défausser le cube sans la dévoiler ; ainsi, la tuile est de nouveau accessible ; s’il n’y a plus de cubes Hercule disponibles, l’Horloge avance et le Traquenard est défaussé ; • Yeux du démon : le malheureux enquêteur croise le regard du démon, sa tête lui tourne et il s’évanouit ; le joueur tourne d’1/4 de tour dans le sens horaire le plateau Lieu de la couleur indiquée sur les Yeux du démon ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Vortex : l’enquêteur entrouvre une faille vers les limbes, la réalité en est toute chamboulée ; le joueur tourne d’1/4 de tour dans le sens horaire TOUS les plateaux Lieux (d’un seul tenant) ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Horloge : quelle perte de temps ! ; l’Horloge avance. S’il n’y a plus de Traquenard disponible, on mélange soigneusement la défausse pour reconstituer la pile de Traquenards. == Capacités spéciales == Chaque Enquêteur dispose d’une Capacité spéciale utilisable à son tour : • Lucile Finemouche : TENACE Relancez une fois le dé Enquête si le résultat ne vous convient pas. Le nouveau résultat doit être appliqué. • Le Balafré : IMPLACCABLE Subissez les effets atténués d’un Traquenard : ne lancez qu’1 seul cube Hercule et ne fermez jamais les yeux face aux Yeux du démon ou au Vortex. • Allison Holmes : INDISCRÈTE Avant de dévoiler vos tuiles, regardez secrètement 1 tuile de votre choix. • Zacahire White : FOUINEUR Avant de dévoiler vos tuiles, regardez secrètement 2 tuiles porteuses d’un Indice ou d’un cube Hercule de votre choix. == Cartes 3ID == Si un joueur a écarté un Suspect à l’Agence 3ID en dévoilant une paire, il pioche 1 carte 3ID : • Les Objets peuvent être utilisées ultérieurement ; un Objet est placé à côté de la fiche Enquêteur du joueur puis défaussé une fois utilisé ; un joueur ne peut posséder qu’un seul Objet ; un Objet en surplus doit être donné à un autre joueur ou défaussé ; • Les Calepins permettent au joueur de prendre un cube Indice supplémentaire à sa couleur ; s’il n’en a plus de disponible, un autre joueur peut prendre un cube Indice supplémentaire à sa couleur ; s’il n’y a plus de cube Indice disponible, la carte est sans effet ; puis la carte est défaussée ; • Les Debriefings permettent au joueur, avant 3 heures, de prendre un cube Indice supplémentaire à sa couleur (comme un Calepin) ; à 3 heures et au-delà, ils permettent de retourner faces visibles toutes les tuiles porteuses d’Indice (les Indices retournent dans la réserve de leur Enquêteur) ; si des paires sont visibles, elles sont immédiatement placées à l’Agence 3ID (en ce cas, on ne pioche pas de carte 3ID et on n’ajoute pas de Traquenard) ; Si, au cours de la partie, la pioche de cartes 3ID est vide, on mélange soigneusement la défausse pour reconstituer la pioche. == Cartes Limbes == Si un joueur n’a pas dévoilé de paire, il pioche 1 carte Limbes : • Les Embûches ont un effet néfaste immédiat ; une fois l’effet d’une Embûche appliqué (ou si l’effet ne peut être appliqué), elle est défaussée ; à noter, certaines Embûches ne font effet qu’à partir de 3 heures ; • Les Malédictions ont un effet néfaste qui s’applique durant un tour de jeu complet ; la Malédiction est laissée face visible devant le joueur qui vient de la piocher ; elle est défaussée à la fin de son prochain tour ; plusieurs cartes Malédiction peuvent cumuler leurs effets. Si, au cours de la partie, la pioche de cartes Limbes est vide, l’Horloge avance et on mélange soigneusement la défausse pour reconstituer la pioche. = Coup de bluff = À partir de 6 heures et au-delà uniquement, à son tour, plutôt que de lancer le dé Enquête, un joueur peut tenter un Coup de bluff : il est intimement convaincu d’avoir découvert, par déduction ou par intuition, l’identité du démon des limbes... • Le joueur dévoile 1 tuile de son choix ; • Puis il dévoile la tuile Démon ; • Si les 2 tuiles sont strictement identiques, la partie est gagnée pour TOUS ; • Si les 2 tuiles sont différentes, la partie est perdue pour TOUS !!! = Fin de partie = Tous les joueurs perdent la partie si : • L’Horloge atteint l’heure des 3 ombres (à la 12ème heure) ; • Un joueur se trompe suite à un Coup de bluff. Tous les joueurs gagnent la partie si : • 13 Suspects ont été écartés à l’Agence 3ID ; • Un joueur réussit son Coup de bluff. Le dernier suspect est donc l’hôte du démon des limbes : les enquêteurs n’ont plus qu’à mener fissa le pauvre possédé au magasin de Mandrakologie pour qu’il y soit désenvoûté et l’esprit maléfique à jamais emprisonné dans une fiole magique d’Ozenbaum. = Descriptif des cartes = == Cartes 3ID == • Archéoscript : À votre tour, jouez 2 fois sans avoir à piocher de carte Limbes ou à ajouter de Traquenard. • Chronogyre : Placez un Indice disponible sur un Suspect que vous venez de dévoiler. Le Suspect est laissé visible jusqu’à ce que sa paire soit reconsituée. • Débriefing : Avant 3h, prenez un Indice à votre couleur. Après 3h, toutes les tuiles porteuses d’Indices sont dévoilées. Si une ou plusieurs paires sont visibles, elles sont placées à l’Agence 3ID. Retournez les autres tuiles faces cachées. • Calepin : Prenez un Indice disponible à votre couleur. S’il n’y en a plus, un autre joueur peut prendre un Indice à sa couleur. • Invertigo : Ignorez l’effet d’une carte Limbes qui vient d’être piochée. • Loupe analytique : Regardez secrètement une tuile de votre choix avant de dévoiler des tuiles. • Stylo traducteur : Relancez le dé Enquête si le résultat ne vous convient pas. Vous devez appliquer l’effet du nouveau résultat. • Révélateur d’empreinte : Écartez tous les cubes Hercule présents sur les Lieux vers le plateau Horloge. • Oreillettes à ultra-son : Regardez secrètement 2 tuiles porteuses d’Indices de votre choix avant de dévoiler des tuiles. == Cartes Limbes == • Amnésie : Tous les Indices présents sur les Lieux sont rendus à leurs Enquêteurs. • Brouillard : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 tuile libre par Lieu et mélangez-les faces cachées puis diposez-en 1 par Lieu à des emplacements libres de votre choix. • Brume : Les joueurs n’ont pas le droit de laisser d’Indice sur les Lieux. • Confusion : Les joueurs ne peuvent pas se servir des Capacités spéciales de leurs Enquêteurs. • Fausse piste : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 paire de Suspects écartés à l’Agence 3ID et mélangez-les faces cachées avec 2 autres tuiles libres de votre choix puis disposez-en 1 par Lieu (si possible) à des emplacements libres de votre choix. • Hallucination : À son tour, un joueur doit intervertir la place des 2 tuiles qu’il vient de dévoiler. • Illusion : Avant 3h, rien ne se passe. À 3h et au-delà, lancez le dé Enquête jusqu’à tomber sur un Lieu et tournez le Lieu désigné d’1/4 de tour dans le sens horaire. • Manipulation : Avant 3h, rien ne se passe. À 3h et au-delà, intervertissez la place des 2 Lieux qui vous font face. • Paralysie : À son tour, un joueur ne peut dévoiler ses tuiles que sur un seul et unique Lieu. • Paranoïa : À son tour, un joueur regarde secrètement ses tuiles sans les montrer. Il peut toutefois les décrire et les dévoiler s’il tombe sur une paire de Suspect. Les Traquenards sont sans effet. • Réveil des ombres : Avant 3h, rien ne se passe. À 3h et au-delà, ajoutez un Traquenard disponible à un emplacement libre de votre choix. • Silence : Les joueurs n’ont pas le droit de parler. Ils peuvent toutefois faire des signes. • Temps accéléré : L’Horloge avance. • Ténèbres : Les joueurs doivent fermer les yeux. À son tour uniquement, un joueur peut ouvrir les yeux puis il doit les refermer dès que son tour est terminé. • Vortex : Avant 3h, rien ne se passe. À 3h et au-delà, tournez tous les Lieux (d’un seul tenant) d’1/4 de tour dans le sens horaire. e481004285df1ea8f1083ac8bc068bd9375b3e66 1988 1987 2016-09-16T11:58:06Z Bigornot 14295 /* Descriptif des cartes */ wikitext text/x-wiki Coopératif • À partir de 8 ans • 2 à 4 joueurs • 30 minutes = L'histoire = Une ombre plane sur Ménilville : Elvyr Ozbaum, mandrakologue pourtant expérimenté, a libéré par inadvertance un démon des limbes. Ce mauvais génie s’est échappé et il est parvenu à se glisser dans l’esprit d’un des habitants du quartier. Depuis, il prend un malin plaisir à hypnotiser d’autres victimes innocentes afin de les pousser à faire n’importe quoi... Mais il y a plus inquiétant : s’il n’est pas chassé avant l’heure des 3 ombres, il prendra définitivement possession de son corps d’emprunt ! Voici un défi pour vous, intrépides enquêteurs de l’Agence 3ID : il vous faut au plus vite découvrir en qui se cache le démon des limbes avant qu’il ne dévore l’âme de sa victime et ne devienne à jamais son double maléfique. Mais avec le chat Hercule qui traîne dans vos pattes et le risque de vous faire envoûter à votre tour, la partie est loin d’être gagnée ! L'heure des 3 ombres est tiré de l'univers de Lucile Finemouche & Le Balafré, éditions Actes Sud Junior. = But du jeu = Sur le principe simple du Memory, il s’agit de reconstituer toutes les paires de personnages afin de déterminer celui dont le double n’est pas en jeu. Les joueurs incarnent des enquêteurs qui doivent coordonner leurs recherches dans Ménilville afin d’écarter un à un les suspects et ainsi débusquer le démon qui se cache parmi eux. Si l’horloge atteint l’heure des 3 ombres (12ème heure), la partie est perdue pour TOUS. Si 13 suspects sont écartés, le démon est démasqué et la partie est gagnée pour TOUS. = Tour de jeu = À son tour, un joueur doit lancer le dé Enquête puis appliquer son résultat. • Faces Réverbère / Chapeau / Pentacle / Rouage : le joueur dévoile 1 tuile du Lieu désigné par le dé et 1 tuile de son choix (du même Lieu ou d’un autre Lieu) ; si le Lieu désigné ne contient aucune tuile, le joueur ne peut dévoiler qu’1 seule tuile de son choix ; • Face Loupe : le joueur dévoile 2 tuiles de son choix ; • Face Horloge : l’Horloge avance puis le joueur dévoile 2 tuiles de son choix. ATTENTION : chaque Suspect existe en 2 versions (normale et hypnotisée), très proches visuellement l’une de l’autre . Il est donc très facile de les confondre ! Si le joueur dévoile 2 Suspects strictement identiques : • Il place les 2 tuiles en pile faces visibles à un emplacement libre du plateau Agence 3ID ; il parvient à innocenter un suspect et le mène illico à l’Agence afin qu’il y soit en sécurité ; • Il pioche une carte 3ID ; de retour au bureau, il récupère du matériel ; • Puis il prend, sans la regarder, 1 tuile Traquenard disponible et la place, face cachée, à un emplacement libre d’un Lieu de son choix ; durant l’absence de l’enquêteur, le démon en profite pour étendre son pouvoir sur Ménilville... Si le joueur dévoile 2 Suspects différents : • Il retourne les tuiles visibles faces cachées ; • Il peut, s’il le souhaite, y placer des Indices de sa réserve ; s’il n’a pas réussi à écarter de suspect, il a tout de même récolté quelques informations ; • Puis il pioche une carte Limbes ; le sort s’acharne ! Si le joueur dévoile 1 Traquenard : • S’il a dévoilé le Traquenard en premier, il en applique immédiatement l’effet sans dévoiler d’autre tuile ; • S’il a dévoilé le Traquenard en second, il retourne face cachée l’autre tuile Suspect qui a été dévoilée avant d’appliquer l’effet du Traquenard ; • Puis il défausse le Traquenard. Une fois son tour effectué, c’est au joueur à sa gauche de lancer le dé Enquête. == Indices == • S’il dévoile 2 Suspects différents, un joueur peut, s’il le souhaite, y laisser des Indices de sa réserve après les avoir retournés faces cachées ; une tuile ne peut accueillir qu’un seul Indice. • Un Indice placé sur une tuile sert simplement à marquer un Suspect, comme un pense-bête laissé en évidence : aux joueur de se souvenir de ce qu’il y a en dessous. • Si un joueur n’a plus d’Indice en réserve, il peut décider de déplacer ses Indices déjà présents sur les Lieux. • Quand une tuile porteuse d’un Indice est dévoilée, l’Indice retourne dans la réserve de son Enquêteur. • Quand une tuile porteuse d’un Indice est regardée secrètement, l’Indice reste sur la tuile. == Traquenards == Si le joueur dévoile 1 Traquenard, il doit en appliquer les effets : • Hercule : ce satané matou prend un malin plaisir à ralentir l’enquête ; le joueur jette 2 cubes Hercule vers le centre des 4 Lieux ; chaque cube Hercule est placé sur la tuile libre face cachée objectivement la plus proche ; une tuile porteuse d’un cube Hercule ne peut être ni regardée, ni dévoilée, ni mélangée ; à son tour, à la place de dévoiler 1 tuile, un joueur peut désigner 1 tuile porteuse d’un cube Hercule pour défausser le cube sans la dévoiler ; ainsi, la tuile est de nouveau accessible ; s’il n’y a plus de cubes Hercule disponibles, l’Horloge avance et le Traquenard est défaussé ; • Yeux du démon : le malheureux enquêteur croise le regard du démon, sa tête lui tourne et il s’évanouit ; le joueur tourne d’1/4 de tour dans le sens horaire le plateau Lieu de la couleur indiquée sur les Yeux du démon ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Vortex : l’enquêteur entrouvre une faille vers les limbes, la réalité en est toute chamboulée ; le joueur tourne d’1/4 de tour dans le sens horaire TOUS les plateaux Lieux (d’un seul tenant) ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Horloge : quelle perte de temps ! ; l’Horloge avance. S’il n’y a plus de Traquenard disponible, on mélange soigneusement la défausse pour reconstituer la pile de Traquenards. == Capacités spéciales == Chaque Enquêteur dispose d’une Capacité spéciale utilisable à son tour : • Lucile Finemouche : TENACE Relancez une fois le dé Enquête si le résultat ne vous convient pas. Le nouveau résultat doit être appliqué. • Le Balafré : IMPLACCABLE Subissez les effets atténués d’un Traquenard : ne lancez qu’1 seul cube Hercule et ne fermez jamais les yeux face aux Yeux du démon ou au Vortex. • Allison Holmes : INDISCRÈTE Avant de dévoiler vos tuiles, regardez secrètement 1 tuile de votre choix. • Zacahire White : FOUINEUR Avant de dévoiler vos tuiles, regardez secrètement 2 tuiles porteuses d’un Indice ou d’un cube Hercule de votre choix. == Cartes 3ID == Si un joueur a écarté un Suspect à l’Agence 3ID en dévoilant une paire, il pioche 1 carte 3ID : • Les Objets peuvent être utilisées ultérieurement ; un Objet est placé à côté de la fiche Enquêteur du joueur puis défaussé une fois utilisé ; un joueur ne peut posséder qu’un seul Objet ; un Objet en surplus doit être donné à un autre joueur ou défaussé ; • Les Calepins permettent au joueur de prendre un cube Indice supplémentaire à sa couleur ; s’il n’en a plus de disponible, un autre joueur peut prendre un cube Indice supplémentaire à sa couleur ; s’il n’y a plus de cube Indice disponible, la carte est sans effet ; puis la carte est défaussée ; • Les Debriefings permettent au joueur, avant 3 heures, de prendre un cube Indice supplémentaire à sa couleur (comme un Calepin) ; à 3 heures et au-delà, ils permettent de retourner faces visibles toutes les tuiles porteuses d’Indice (les Indices retournent dans la réserve de leur Enquêteur) ; si des paires sont visibles, elles sont immédiatement placées à l’Agence 3ID (en ce cas, on ne pioche pas de carte 3ID et on n’ajoute pas de Traquenard) ; Si, au cours de la partie, la pioche de cartes 3ID est vide, on mélange soigneusement la défausse pour reconstituer la pioche. == Cartes Limbes == Si un joueur n’a pas dévoilé de paire, il pioche 1 carte Limbes : • Les Embûches ont un effet néfaste immédiat ; une fois l’effet d’une Embûche appliqué (ou si l’effet ne peut être appliqué), elle est défaussée ; à noter, certaines Embûches ne font effet qu’à partir de 3 heures ; • Les Malédictions ont un effet néfaste qui s’applique durant un tour de jeu complet ; la Malédiction est laissée face visible devant le joueur qui vient de la piocher ; elle est défaussée à la fin de son prochain tour ; plusieurs cartes Malédiction peuvent cumuler leurs effets. Si, au cours de la partie, la pioche de cartes Limbes est vide, l’Horloge avance et on mélange soigneusement la défausse pour reconstituer la pioche. = Coup de bluff = À partir de 6 heures et au-delà uniquement, à son tour, plutôt que de lancer le dé Enquête, un joueur peut tenter un Coup de bluff : il est intimement convaincu d’avoir découvert, par déduction ou par intuition, l’identité du démon des limbes... • Le joueur dévoile 1 tuile de son choix ; • Puis il dévoile la tuile Démon ; • Si les 2 tuiles sont strictement identiques, la partie est gagnée pour TOUS ; • Si les 2 tuiles sont différentes, la partie est perdue pour TOUS !!! = Fin de partie = Tous les joueurs perdent la partie si : • L’Horloge atteint l’heure des 3 ombres (à la 12ème heure) ; • Un joueur se trompe suite à un Coup de bluff. Tous les joueurs gagnent la partie si : • 13 Suspects ont été écartés à l’Agence 3ID ; • Un joueur réussit son Coup de bluff. Le dernier suspect est donc l’hôte du démon des limbes : les enquêteurs n’ont plus qu’à mener fissa le pauvre possédé au magasin de Mandrakologie pour qu’il y soit désenvoûté et l’esprit maléfique à jamais emprisonné dans une fiole magique d’Ozenbaum. = Descriptif des cartes = == Cartes 3ID == • Archéoscript : À votre tour, jouez 2 fois sans avoir à piocher de carte Limbes ou à ajouter de Traquenard. • Chronogyre : Placez un Indice disponible sur un Suspect que vous venez de dévoiler. Le Suspect est laissé visible jusqu’à ce que sa paire soit reconsituée. • Débriefing : Avant 3h, prenez un Indice à votre couleur. Après 3h, toutes les tuiles porteuses d’Indices sont dévoilées. Si une ou plusieurs paires sont visibles, elles sont placées à l’Agence 3ID. Retournez les autres tuiles faces cachées. • Calepin : Prenez un Indice disponible à votre couleur. S’il n’y en a plus, un autre joueur peut prendre un Indice à sa couleur. • Invertigo : Ignorez l’effet d’une carte Limbes qui vient d’être piochée. • Loupe analytique : Regardez secrètement une tuile de votre choix avant de dévoiler des tuiles. • Stylo traducteur : Relancez le dé Enquête si le résultat ne vous convient pas. Vous devez appliquer l’effet du nouveau résultat. • Révélateur d’empreinte : Écartez tous les cubes Hercule présents sur les Lieux vers le plateau Horloge. • Oreillettes à ultra-son : Regardez secrètement 2 tuiles porteuses d’Indices de votre choix avant de dévoiler des tuiles. == Cartes Limbes == • Amnésie : Tous les Indices présents sur les Lieux sont rendus à leurs Enquêteurs. • Brouillard : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 tuile libre par Lieu et mélangez-les faces cachées puis diposez-en 1 par Lieu à des emplacements libres de votre choix. • Brume : Les joueurs n’ont pas le droit de laisser d’Indice sur les Lieux. • Confusion : Les joueurs ne peuvent pas se servir des Capacités spéciales de leurs Enquêteurs. • Fausse piste : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 paire de Suspects écartés à l’Agence 3ID et mélangez-les faces cachées avec 2 autres tuiles libres de votre choix puis disposez-en 1 par Lieu (si possible) à des emplacements libres de votre choix. • Hallucination : À son tour, un joueur doit intervertir la place des 2 tuiles qu’il vient de dévoiler. • Illusion : Avant 3h, rien ne se passe. À 3h et au-delà, lancez le dé Enquête jusqu’à tomber sur un Lieu et tournez le Lieu désigné d’1/4 de tour dans le sens horaire. • Manipulation : Avant 3h, rien ne se passe. À 3h et au-delà, intervertissez la place des 2 Lieux qui vous font face. • Paralysie : À son tour, un joueur ne peut dévoiler ses tuiles que sur un seul et unique Lieu. • Paranoïa : À son tour, un joueur regarde secrètement ses tuiles sans les montrer. Il peut toutefois les décrire et les dévoiler s’il tombe sur une paire de Suspect. Les Traquenards sont sans effet. • Réveil des ombres : Avant 3h, rien ne se passe. À 3h et au-delà, ajoutez un Traquenard disponible à un emplacement libre de votre choix. • Silence : Les joueurs n’ont pas le droit de parler. Ils peuvent toutefois faire des signes. • Temps accéléré : L’Horloge avance. • Ténèbres : Les joueurs doivent fermer les yeux. À son tour uniquement, un joueur peut ouvrir les yeux puis il doit les refermer dès que son tour est terminé. • Vortex : Avant 3h, rien ne se passe. À 3h et au-delà, tournez tous les Lieux (d’un seul tenant) d’1/4 de tour dans le sens horaire. 15e3ce8e62ed5769914b6ebebce112471d52d380 1989 1988 2016-09-16T11:59:00Z Bigornot 14295 /* Tour de jeu */ wikitext text/x-wiki Coopératif • À partir de 8 ans • 2 à 4 joueurs • 30 minutes = L'histoire = Une ombre plane sur Ménilville : Elvyr Ozbaum, mandrakologue pourtant expérimenté, a libéré par inadvertance un démon des limbes. Ce mauvais génie s’est échappé et il est parvenu à se glisser dans l’esprit d’un des habitants du quartier. Depuis, il prend un malin plaisir à hypnotiser d’autres victimes innocentes afin de les pousser à faire n’importe quoi... Mais il y a plus inquiétant : s’il n’est pas chassé avant l’heure des 3 ombres, il prendra définitivement possession de son corps d’emprunt ! Voici un défi pour vous, intrépides enquêteurs de l’Agence 3ID : il vous faut au plus vite découvrir en qui se cache le démon des limbes avant qu’il ne dévore l’âme de sa victime et ne devienne à jamais son double maléfique. Mais avec le chat Hercule qui traîne dans vos pattes et le risque de vous faire envoûter à votre tour, la partie est loin d’être gagnée ! L'heure des 3 ombres est tiré de l'univers de Lucile Finemouche & Le Balafré, éditions Actes Sud Junior. = But du jeu = Sur le principe simple du Memory, il s’agit de reconstituer toutes les paires de personnages afin de déterminer celui dont le double n’est pas en jeu. Les joueurs incarnent des enquêteurs qui doivent coordonner leurs recherches dans Ménilville afin d’écarter un à un les suspects et ainsi débusquer le démon qui se cache parmi eux. Si l’horloge atteint l’heure des 3 ombres (12ème heure), la partie est perdue pour TOUS. Si 13 suspects sont écartés, le démon est démasqué et la partie est gagnée pour TOUS. = Tour de jeu = À son tour, un joueur doit lancer le dé Enquête puis appliquer son résultat. • Faces Réverbère / Chapeau / Pentacle / Rouage : le joueur dévoile 1 tuile du Lieu désigné par le dé et 1 tuile de son choix (du même Lieu ou d’un autre Lieu) ; si le Lieu désigné ne contient aucune tuile, le joueur ne peut dévoiler qu’1 seule tuile de son choix ; • Face Loupe : le joueur dévoile 2 tuiles de son choix ; • Face Horloge : l’Horloge avance puis le joueur dévoile 2 tuiles de son choix. ATTENTION : chaque Suspect existe en 2 versions (normale et hypnotisée), très proches visuellement l’une de l’autre . Il est donc très facile de les confondre ! Si le joueur dévoile 2 Suspects strictement identiques : • Il place les 2 tuiles en pile faces visibles à un emplacement libre du plateau Agence 3ID ; il parvient à innocenter un suspect et le mène illico à l’Agence afin qu’il y soit en sécurité ; • Il pioche une carte 3ID ; de retour au bureau, il récupère du matériel ; • Puis il prend, sans la regarder, 1 tuile Traquenard disponible et la place, face cachée, à un emplacement libre d’un Lieu de son choix ; durant l’absence de l’enquêteur, le démon en profite pour étendre son pouvoir sur Ménilville... Si le joueur dévoile 2 Suspects différents : • Il retourne les tuiles visibles faces cachées ; • Il peut, s’il le souhaite, y placer des Indices de sa réserve ; s’il n’a pas réussi à écarter de suspect, il a tout de même récolté quelques informations ; • Puis il pioche une carte Limbes ; le sort s’acharne ! Si le joueur dévoile 1 Traquenard : • S’il a dévoilé le Traquenard en premier, il en applique immédiatement l’effet sans dévoiler d’autre tuile ; • S’il a dévoilé le Traquenard en second, il retourne face cachée l’autre tuile Suspect qui a été dévoilée avant d’appliquer l’effet du Traquenard ; • Puis il défausse le Traquenard. Une fois son tour effectué, c’est au joueur à sa gauche de lancer le dé Enquête. == Indices == • S’il dévoile 2 Suspects différents, un joueur peut, s’il le souhaite, y laisser des Indices de sa réserve après les avoir retournés faces cachées ; une tuile ne peut accueillir qu’un seul Indice. • Un Indice placé sur une tuile sert simplement à marquer un Suspect, comme un pense-bête laissé en évidence : aux joueur de se souvenir de ce qu’il y a en dessous. • Si un joueur n’a plus d’Indice en réserve, il peut décider de déplacer ses Indices déjà présents sur les Lieux. • Quand une tuile porteuse d’un Indice est dévoilée, l’Indice retourne dans la réserve de son Enquêteur. • Quand une tuile porteuse d’un Indice est regardée secrètement, l’Indice reste sur la tuile. == Traquenards == Si le joueur dévoile 1 Traquenard, il doit en appliquer les effets : • Hercule : ce satané matou prend un malin plaisir à ralentir l’enquête ; le joueur jette 2 cubes Hercule vers le centre des 4 Lieux ; chaque cube Hercule est placé sur la tuile libre face cachée objectivement la plus proche ; une tuile porteuse d’un cube Hercule ne peut être ni regardée, ni dévoilée, ni mélangée ; à son tour, à la place de dévoiler 1 tuile, un joueur peut désigner 1 tuile porteuse d’un cube Hercule pour défausser le cube sans la dévoiler ; ainsi, la tuile est de nouveau accessible ; s’il n’y a plus de cubes Hercule disponibles, l’Horloge avance et le Traquenard est défaussé ; • Yeux du démon : le malheureux enquêteur croise le regard du démon, sa tête lui tourne et il s’évanouit ; le joueur tourne d’1/4 de tour dans le sens horaire le plateau Lieu de la couleur indiquée sur les Yeux du démon ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Vortex : l’enquêteur entrouvre une faille vers les limbes, la réalité en est toute chamboulée ; le joueur tourne d’1/4 de tour dans le sens horaire TOUS les plateaux Lieux (d’un seul tenant) ; puis le joueur doit fermer les yeux jusqu’à son prochain tour ; • Horloge : quelle perte de temps ! ; l’Horloge avance. S’il n’y a plus de Traquenard disponible, on mélange soigneusement la défausse pour reconstituer la pile de Traquenards. == Capacités spéciales == Chaque Enquêteur dispose d’une Capacité spéciale utilisable à son tour : • Lucile Finemouche : TENACE Relancez une fois le dé Enquête si le résultat ne vous convient pas. Le nouveau résultat doit être appliqué. • Le Balafré : IMPLACCABLE Subissez les effets atténués d’un Traquenard : ne lancez qu’1 seul cube Hercule et ne fermez jamais les yeux face aux Yeux du démon ou au Vortex. • Allison Holmes : INDISCRÈTE Avant de dévoiler vos tuiles, regardez secrètement 1 tuile de votre choix. • Zacahire White : FOUINEUR Avant de dévoiler vos tuiles, regardez secrètement 2 tuiles porteuses d’un Indice ou d’un cube Hercule de votre choix. == Cartes 3ID == Si un joueur a écarté un Suspect à l’Agence 3ID en dévoilant une paire, il pioche 1 carte 3ID : • Les Objets peuvent être utilisées ultérieurement ; un Objet est placé à côté de la fiche Enquêteur du joueur puis défaussé une fois utilisé ; un joueur ne peut posséder qu’un seul Objet ; un Objet en surplus doit être donné à un autre joueur ou défaussé ; • Les Calepins permettent au joueur de prendre un cube Indice supplémentaire à sa couleur ; s’il n’en a plus de disponible, un autre joueur peut prendre un cube Indice supplémentaire à sa couleur ; s’il n’y a plus de cube Indice disponible, la carte est sans effet ; puis la carte est défaussée ; • Les Debriefings permettent au joueur, avant 3 heures, de prendre un cube Indice supplémentaire à sa couleur (comme un Calepin) ; à 3 heures et au-delà, ils permettent de retourner faces visibles toutes les tuiles porteuses d’Indice (les Indices retournent dans la réserve de leur Enquêteur) ; si des paires sont visibles, elles sont immédiatement placées à l’Agence 3ID (en ce cas, on ne pioche pas de carte 3ID et on n’ajoute pas de Traquenard) ; Si, au cours de la partie, la pioche de cartes 3ID est vide, on mélange soigneusement la défausse pour reconstituer la pioche. == Cartes Limbes == Si un joueur n’a pas dévoilé de paire, il pioche 1 carte Limbes : • Les Embûches ont un effet néfaste immédiat ; une fois l’effet d’une Embûche appliqué (ou si l’effet ne peut être appliqué), elle est défaussée ; à noter, certaines Embûches ne font effet qu’à partir de 3 heures ; • Les Malédictions ont un effet néfaste qui s’applique durant un tour de jeu complet ; la Malédiction est laissée face visible devant le joueur qui vient de la piocher ; elle est défaussée à la fin de son prochain tour ; plusieurs cartes Malédiction peuvent cumuler leurs effets. Si, au cours de la partie, la pioche de cartes Limbes est vide, l’Horloge avance et on mélange soigneusement la défausse pour reconstituer la pioche. = Coup de bluff = À partir de 6 heures et au-delà uniquement, à son tour, plutôt que de lancer le dé Enquête, un joueur peut tenter un Coup de bluff : il est intimement convaincu d’avoir découvert, par déduction ou par intuition, l’identité du démon des limbes... • Le joueur dévoile 1 tuile de son choix ; • Puis il dévoile la tuile Démon ; • Si les 2 tuiles sont strictement identiques, la partie est gagnée pour TOUS ; • Si les 2 tuiles sont différentes, la partie est perdue pour TOUS !!! = Fin de partie = Tous les joueurs perdent la partie si : • L’Horloge atteint l’heure des 3 ombres (à la 12ème heure) ; • Un joueur se trompe suite à un Coup de bluff. Tous les joueurs gagnent la partie si : • 13 Suspects ont été écartés à l’Agence 3ID ; • Un joueur réussit son Coup de bluff. Le dernier suspect est donc l’hôte du démon des limbes : les enquêteurs n’ont plus qu’à mener fissa le pauvre possédé au magasin de Mandrakologie pour qu’il y soit désenvoûté et l’esprit maléfique à jamais emprisonné dans une fiole magique d’Ozenbaum. = Descriptif des cartes = == Cartes 3ID == • Archéoscript : À votre tour, jouez 2 fois sans avoir à piocher de carte Limbes ou à ajouter de Traquenard. • Chronogyre : Placez un Indice disponible sur un Suspect que vous venez de dévoiler. Le Suspect est laissé visible jusqu’à ce que sa paire soit reconsituée. • Débriefing : Avant 3h, prenez un Indice à votre couleur. Après 3h, toutes les tuiles porteuses d’Indices sont dévoilées. Si une ou plusieurs paires sont visibles, elles sont placées à l’Agence 3ID. Retournez les autres tuiles faces cachées. • Calepin : Prenez un Indice disponible à votre couleur. S’il n’y en a plus, un autre joueur peut prendre un Indice à sa couleur. • Invertigo : Ignorez l’effet d’une carte Limbes qui vient d’être piochée. • Loupe analytique : Regardez secrètement une tuile de votre choix avant de dévoiler des tuiles. • Stylo traducteur : Relancez le dé Enquête si le résultat ne vous convient pas. Vous devez appliquer l’effet du nouveau résultat. • Révélateur d’empreinte : Écartez tous les cubes Hercule présents sur les Lieux vers le plateau Horloge. • Oreillettes à ultra-son : Regardez secrètement 2 tuiles porteuses d’Indices de votre choix avant de dévoiler des tuiles. == Cartes Limbes == • Amnésie : Tous les Indices présents sur les Lieux sont rendus à leurs Enquêteurs. • Brouillard : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 tuile libre par Lieu et mélangez-les faces cachées puis diposez-en 1 par Lieu à des emplacements libres de votre choix. • Brume : Les joueurs n’ont pas le droit de laisser d’Indice sur les Lieux. • Confusion : Les joueurs ne peuvent pas se servir des Capacités spéciales de leurs Enquêteurs. • Fausse piste : Avant 3h, rien ne se passe. À 3h et au-delà, choisissez 1 paire de Suspects écartés à l’Agence 3ID et mélangez-les faces cachées avec 2 autres tuiles libres de votre choix puis disposez-en 1 par Lieu (si possible) à des emplacements libres de votre choix. • Hallucination : À son tour, un joueur doit intervertir la place des 2 tuiles qu’il vient de dévoiler. • Illusion : Avant 3h, rien ne se passe. À 3h et au-delà, lancez le dé Enquête jusqu’à tomber sur un Lieu et tournez le Lieu désigné d’1/4 de tour dans le sens horaire. • Manipulation : Avant 3h, rien ne se passe. À 3h et au-delà, intervertissez la place des 2 Lieux qui vous font face. • Paralysie : À son tour, un joueur ne peut dévoiler ses tuiles que sur un seul et unique Lieu. • Paranoïa : À son tour, un joueur regarde secrètement ses tuiles sans les montrer. Il peut toutefois les décrire et les dévoiler s’il tombe sur une paire de Suspect. Les Traquenards sont sans effet. • Réveil des ombres : Avant 3h, rien ne se passe. À 3h et au-delà, ajoutez un Traquenard disponible à un emplacement libre de votre choix. • Silence : Les joueurs n’ont pas le droit de parler. Ils peuvent toutefois faire des signes. • Temps accéléré : L’Horloge avance. • Ténèbres : Les joueurs doivent fermer les yeux. À son tour uniquement, un joueur peut ouvrir les yeux puis il doit les refermer dès que son tour est terminé. • Vortex : Avant 3h, rien ne se passe. À 3h et au-delà, tournez tous les Lieux (d’un seul tenant) d’1/4 de tour dans le sens horaire. 747abc3fcfb6611967bce387273e1da5a8095846 Gamehelpmadeira 0 231 1995 2016-09-19T21:55:03Z Greenman 1407 Created page with "==Reference Sheet== ===Crown’s Requests=== During Phase E, each player must choose 1 of his Crown’s Requests in the 1st round, 2 in the 3rd round, and 3 in the 5th round..." wikitext text/x-wiki ==Reference Sheet== ===Crown’s Requests=== During Phase E, each player must choose 1 of his Crown’s Requests in the 1st round, 2 in the 3rd round, and 3 in the 5th round. He earns PP for them, and discards them. NOTE: If a player chooses more than 1 Crown’s Request of the same kind in the same round, he must assign different items to them (see below Urbanization for an example). The player must discard all the chosen Crown’s Requests, even if he earns 0 Prestige Points for one or more of them. ===Guild Favors=== A player can use 1 of his face-up Guild Favors at the beginning of each of his turns: * in Phase B - Character Actions (see page 9) (i.e. before he places a die or passes) and * in Phase C - Building Actions (see page 12) (i.e. before he pays the cost or receives the Pirates). He cannot use a Guild Favor if he has no Action Markers on the Building currently being resolved, because it is not his turn. To use a Guild Favor, the player flips it face-down and immediately applies its effect (see below). No Guild Favors can be used during Phases A - Round Setup, D - Maintenance, or E - The Crown’s Requests. Reminder: A player can flip face-up: * in Phase A - Round Setup, all of his Guild Favors of the same Guild as the one he chooses (see page 8). * 1 or 2 of his Guild Favors (same or different Guilds), performing the “Casa da Coroa” Building Action (see page 13). * 1 of his Guild Favors, performing the “Guild” King’s Reward, if it is in play, (see below). ===Passing=== * The player gets 2 Reals *The player gets 3 Reals ** OR earns 1 PP, and may move 1 of his Workers to any empty City spot * The player gets 4 Reals ** OR moves 1 of his Workers into the City Watch * The player gets 5 Reals ** OR moves 1 of his Ships following the usual rules ===King’s Rewards=== Various Rewards available * The player moves 1 of his Workers to any field following the usual rules * The player flips 1 of his Guild Favors face-up. * The player discards up to 3 Pirates or gets 2 Bread from the general supply. * The player moves his disc up one step in the Windmill. He does not discard the 2 Wheat. * The player earns 3 PP. The player gets 5 Reals. * The player earns 1 PP, and may move 1 of his Workers to any empty City spot. * The player moves 1 of his Workers into the City Watch 0ce51145fa179919862c94c9ea90ba0e1c7ea4a2 1996 1995 2016-09-20T13:27:59Z Nandblock 11082 Trying to condense the basic turn rules to something manageable - I find the rulebook's version rather opaque wikitext text/x-wiki == PHASE A: SETUP AND GUILD CHOICE == The four character tiles are randomly distributed among the five buildings (one remains empty each turn, as indicated by the building number). 3 pirate dice are rolled and placed in the City Watch. 3 guild dice per player are rolled and placed in rows on the Guild Board. Each player in turn places their marker on a row and selects the corresponding dice and one request. If the guild symbol matches any of their guild favours they flip them face up. == PHASE B: CHARACTER ACTIONS == Following the new turn order established in Phase A, players either select a character action or pass. A character action is selected by placing on it either a guild die or (at the cost of a worker in the City Watch) a pirate die. If a guild die is used, the player also places an action marker on the building space (to be resolved in Phase C). You may activate a character with a die whose value is equal to or greater than the number of that character’s region (1, 2 or 3). You may also use a lower-numbered die by paying the difference in bread. A character may have a maximum of 1 pirate die on it, and a maximum number of dice equal to the number of players. A player may choose one of two possible character actions: - Trigger the action specific to the character. - Harvest: all fields in that region will yield one unit per worker: either wood (if they have not yet been cleared) or a crop (wheat, sugar or wine). One building each round contains no character card, so it only offers the harvest action, plus a bonus: one field is harvested twice. === Passing === To pass, a player chooses a free spot in the passing column: they may either choose to gain reals, or take the action depicted. The new turn order will be observed for the rest of the round and the beginning of the next. == PHASE C: BUILDING ACTIONS == In numerical order, building costs are resolved and additional building actions are taken. For any building with action markers on it, all its dice are rolled. The cost is (in a four-player game) 10 reals minus the sum of the guild dice. (In three or two player games, the base value is respectively 9 or 8.) If the result is negative the cost is zero. If a player has two or more markers they still pay only once. Players have two options: - Pay the cost, and take the building action (described below) - Take pirates (1 + the number on the pirate die, if there is one) == PHASE D: MAINTENANCE == Honor (City Watch): The player with the majority of workers in the City Watch may send one home to earn 4 PP. Ties do not count. Income (Colonies): One good of the appropriate type is gained for each worker in the colonies. Upkeep (Ships): Discard 1 wood (or earn 1 pirate) per ship on the board. Feeding Workers: All workers on the board must be fed. The Windmill indicates how many are automatically fed; if this is insufficient, pay 1 bread or earn 1 pirate per worker. == PHASE E: CROWN’S REQUESTS == In rounds 1, 3 and 5 players score their requests. In round 1, they may score one of their two requests; in round 3, two out of three; in round 5, all three. Scored requests, and any goods or reals used to score them, are discarded. In round 2, convertible wheat fields cleared of wood become sugar fields. In round 4, convertible sugar fields cleared of wood become wine fields. == GAME END == The game ends after 5 rounds. All goods, wood and bread are converted to reals at 1-for-1. Players then earn 1 PP per 5 reals. Players with pirates lose points as follows: the one with most pirates loses 16 PP; 2nd most, 8 pp; 3rd most, 4 pp; 4th most, 2 PP. In addition, players lose 1 PP for each pirate over 20. Highest score wins. Ties for number of pirates or for final score go to the player earliest in the turn order. ==Reference Sheet== ===Crown’s Requests=== During Phase E, each player must choose 1 of his Crown’s Requests in the 1st round, 2 in the 3rd round, and 3 in the 5th round. He earns PP for them, and discards them. NOTE: If a player chooses more than 1 Crown’s Request of the same kind in the same round, he must assign different items to them (see below Urbanization for an example). The player must discard all the chosen Crown’s Requests, even if he earns 0 Prestige Points for one or more of them. ===Guild Favors=== A player can use 1 of his face-up Guild Favors at the beginning of each of his turns: * in Phase B - Character Actions (see page 9) (i.e. before he places a die or passes) and * in Phase C - Building Actions (see page 12) (i.e. before he pays the cost or receives the Pirates). He cannot use a Guild Favor if he has no Action Markers on the Building currently being resolved, because it is not his turn. To use a Guild Favor, the player flips it face-down and immediately applies its effect (see below). No Guild Favors can be used during Phases A - Round Setup, D - Maintenance, or E - The Crown’s Requests. Reminder: A player can flip face-up: * in Phase A - Round Setup, all of his Guild Favors of the same Guild as the one he chooses (see page 8). * 1 or 2 of his Guild Favors (same or different Guilds), performing the “Casa da Coroa” Building Action (see page 13). * 1 of his Guild Favors, performing the “Guild” King’s Reward, if it is in play, (see below). ===Passing=== * The player gets 2 Reals *The player gets 3 Reals ** OR earns 1 PP, and may move 1 of his Workers to any empty City spot * The player gets 4 Reals ** OR moves 1 of his Workers into the City Watch * The player gets 5 Reals ** OR moves 1 of his Ships following the usual rules ===King’s Rewards=== Various Rewards available * The player moves 1 of his Workers to any field following the usual rules * The player flips 1 of his Guild Favors face-up. * The player discards up to 3 Pirates or gets 2 Bread from the general supply. * The player moves his disc up one step in the Windmill. He does not discard the 2 Wheat. * The player earns 3 PP. The player gets 5 Reals. * The player earns 1 PP, and may move 1 of his Workers to any empty City spot. * The player moves 1 of his Workers into the City Watch b59a1ace3e4f9d141913e259a947766a8ce5134e 1997 1996 2016-09-20T16:50:19Z Nandblock 11082 /* PHASE A: SETUP AND GUILD CHOICE */ wikitext text/x-wiki == PHASE A: SETUP AND GUILD CHOICE == The four character tiles are randomly distributed among the five buildings (one remains empty each turn, as indicated by the roman numeral on its top right). 3 pirate dice are rolled and placed in the City Watch. 3 guild dice per player are rolled and placed in rows on the Guild Board. Each player in turn places their marker on a row and selects the corresponding dice and one request. If the guild symbol matches any of their guild favours they flip them face up. == PHASE B: CHARACTER ACTIONS == Following the new turn order established in Phase A, players either select a character action or pass. A character action is selected by placing on it either a guild die or (at the cost of a worker in the City Watch) a pirate die. If a guild die is used, the player also places an action marker on the building space (to be resolved in Phase C). You may activate a character with a die whose value is equal to or greater than the number of that character’s region (1, 2 or 3). You may also use a lower-numbered die by paying the difference in bread. A character may have a maximum of 1 pirate die on it, and a maximum number of dice equal to the number of players. A player may choose one of two possible character actions: - Trigger the action specific to the character. - Harvest: all fields in that region will yield one unit per worker: either wood (if they have not yet been cleared) or a crop (wheat, sugar or wine). One building each round contains no character card, so it only offers the harvest action, plus a bonus: one field is harvested twice. === Passing === To pass, a player chooses a free spot in the passing column: they may either choose to gain reals, or take the action depicted. The new turn order will be observed for the rest of the round and the beginning of the next. == PHASE C: BUILDING ACTIONS == In numerical order, building costs are resolved and additional building actions are taken. For any building with action markers on it, all its dice are rolled. The cost is (in a four-player game) 10 reals minus the sum of the guild dice. (In three or two player games, the base value is respectively 9 or 8.) If the result is negative the cost is zero. If a player has two or more markers they still pay only once. Players have two options: - Pay the cost, and take the building action (described below) - Take pirates (1 + the number on the pirate die, if there is one) == PHASE D: MAINTENANCE == Honor (City Watch): The player with the majority of workers in the City Watch may send one home to earn 4 PP. Ties do not count. Income (Colonies): One good of the appropriate type is gained for each worker in the colonies. Upkeep (Ships): Discard 1 wood (or earn 1 pirate) per ship on the board. Feeding Workers: All workers on the board must be fed. The Windmill indicates how many are automatically fed; if this is insufficient, pay 1 bread or earn 1 pirate per worker. == PHASE E: CROWN’S REQUESTS == In rounds 1, 3 and 5 players score their requests. In round 1, they may score one of their two requests; in round 3, two out of three; in round 5, all three. Scored requests, and any goods or reals used to score them, are discarded. In round 2, convertible wheat fields cleared of wood become sugar fields. In round 4, convertible sugar fields cleared of wood become wine fields. == GAME END == The game ends after 5 rounds. All goods, wood and bread are converted to reals at 1-for-1. Players then earn 1 PP per 5 reals. Players with pirates lose points as follows: the one with most pirates loses 16 PP; 2nd most, 8 pp; 3rd most, 4 pp; 4th most, 2 PP. In addition, players lose 1 PP for each pirate over 20. Highest score wins. Ties for number of pirates or for final score go to the player earliest in the turn order. ==Reference Sheet== ===Crown’s Requests=== During Phase E, each player must choose 1 of his Crown’s Requests in the 1st round, 2 in the 3rd round, and 3 in the 5th round. He earns PP for them, and discards them. NOTE: If a player chooses more than 1 Crown’s Request of the same kind in the same round, he must assign different items to them (see below Urbanization for an example). The player must discard all the chosen Crown’s Requests, even if he earns 0 Prestige Points for one or more of them. ===Guild Favors=== A player can use 1 of his face-up Guild Favors at the beginning of each of his turns: * in Phase B - Character Actions (see page 9) (i.e. before he places a die or passes) and * in Phase C - Building Actions (see page 12) (i.e. before he pays the cost or receives the Pirates). He cannot use a Guild Favor if he has no Action Markers on the Building currently being resolved, because it is not his turn. To use a Guild Favor, the player flips it face-down and immediately applies its effect (see below). No Guild Favors can be used during Phases A - Round Setup, D - Maintenance, or E - The Crown’s Requests. Reminder: A player can flip face-up: * in Phase A - Round Setup, all of his Guild Favors of the same Guild as the one he chooses (see page 8). * 1 or 2 of his Guild Favors (same or different Guilds), performing the “Casa da Coroa” Building Action (see page 13). * 1 of his Guild Favors, performing the “Guild” King’s Reward, if it is in play, (see below). ===Passing=== * The player gets 2 Reals *The player gets 3 Reals ** OR earns 1 PP, and may move 1 of his Workers to any empty City spot * The player gets 4 Reals ** OR moves 1 of his Workers into the City Watch * The player gets 5 Reals ** OR moves 1 of his Ships following the usual rules ===King’s Rewards=== Various Rewards available * The player moves 1 of his Workers to any field following the usual rules * The player flips 1 of his Guild Favors face-up. * The player discards up to 3 Pirates or gets 2 Bread from the general supply. * The player moves his disc up one step in the Windmill. He does not discard the 2 Wheat. * The player earns 3 PP. The player gets 5 Reals. * The player earns 1 PP, and may move 1 of his Workers to any empty City spot. * The player moves 1 of his Workers into the City Watch 019b6609e10ef336677f241d3ed17c243f9a85b7 1998 1997 2016-09-20T16:53:29Z Nandblock 11082 Adding more stuff.... wikitext text/x-wiki = Elements of Gameplay = == Pirates == Pirates are black marks that indicate your failure to pay debts (e.g., to feed your workers or pay the cost of an action). They have no effect on your score until game end. Pirate dice are black dice placed in the City Watch, which may be used by any player to take actions in Phase B (see City Watch below). They will only give pirates to players if they fail to pay a building cost in Phase C. == City Watch == Workers placed here have two uses: * - In Phase B, send a worker from the City Watch home to make use of a pirate die. * - In Phase D, send a worker from the City Watch home to gain 4 PP. == Windmill == Your standing on the Windmill indicates how many workers on the board you can feed automatically in Phase D, without needing additional bread. In addition, you may use the windmill to take one or more free actions during a turn: DURING PHASES B, C, OR D: * - Exchange 2 goods for 1 good of a different type. (Goods are wheat, sugar, wine.) * - Move up 1 step on the Windmill by discarding 2 wheat. (If you are already on the top step, gain 1 PP instead.) DURING PHASES B OR C ONLY: * - Move down 1 step to gain 1 bread or 2 reals. (If you are already on the bottom step, lose 1 PP to take this action.) = Gameplay = == PHASE A: SETUP AND GUILD CHOICE == The four character tiles are randomly distributed among the five buildings (one remains empty each turn, as indicated by the roman numeral on its top right). 3 pirate dice are rolled and placed in the City Watch. 3 guild dice per player are rolled and placed in rows on the Guild Board. Each player in turn places their marker on a row and selects the corresponding dice and one request. If the guild symbol matches any of their guild favours they flip them face up. == PHASE B: CHARACTER ACTIONS == Following the new turn order established in Phase A, players either select a character action or pass. A character action is selected by placing on it either a guild die or (at the cost of a worker in the City Watch) a pirate die. If a guild die is used, the player also places an action marker on the building space (to be resolved in Phase C). You may activate a character with a die whose value is equal to or greater than the number of that character’s region (1, 2 or 3). You may also use a lower-numbered die by paying the difference in bread. A character may have a maximum of 1 pirate die on it, and a maximum number of dice equal to the number of players. A player may choose one of two possible character actions: - Trigger the action specific to the character. - Harvest: all fields in that region will yield one unit per worker: either wood (if they have not yet been cleared) or a crop (wheat, sugar or wine). One building each round contains no character card, so it only offers the harvest action, plus a bonus: one field is harvested twice. === Passing === To pass, a player chooses a free spot in the passing column: they may either choose to gain reals, or take the action depicted. The new turn order will be observed for the rest of the round and the beginning of the next. == PHASE C: BUILDING ACTIONS == In numerical order, building costs are resolved and additional building actions are taken. For any building with action markers on it, all its dice are rolled. The cost is (in a four-player game) 10 reals minus the sum of the guild dice. (In three or two player games, the base value is respectively 9 or 8.) If the result is negative the cost is zero. If a player has two or more markers they still pay only once. Players have two options: - Pay the cost, and take the building action (described below) - Take pirates (1 + the number on the pirate die, if there is one) == PHASE D: MAINTENANCE == Honor (City Watch): The player with the majority of workers in the City Watch may send one home to earn 4 PP. Ties do not count. Income (Colonies): One good of the appropriate type is gained for each worker in the colonies. Upkeep (Ships): Discard 1 wood (or earn 1 pirate) per ship on the board. Feeding Workers: All workers on the board must be fed. The Windmill indicates how many are automatically fed; if this is insufficient, pay 1 bread or earn 1 pirate per worker. == PHASE E: CROWN’S REQUESTS == In rounds 1, 3 and 5 players score their requests. In round 1, they may score one of their two requests; in round 3, two out of three; in round 5, all three. Scored requests, and any goods or reals used to score them, are discarded. In round 2, convertible wheat fields cleared of wood become sugar fields. In round 4, convertible sugar fields cleared of wood become wine fields. == GAME END == The game ends after 5 rounds. All goods, wood and bread are converted to reals at 1-for-1. Players then earn 1 PP per 5 reals. Players with pirates lose points as follows: the one with most pirates loses 16 PP; 2nd most, 8 pp; 3rd most, 4 pp; 4th most, 2 PP. In addition, players lose 1 PP for each pirate over 20. Highest score wins. Ties for number of pirates or for final score go to the player earliest in the turn order. ==Reference Sheet== ===Crown’s Requests=== During Phase E, each player must choose 1 of his Crown’s Requests in the 1st round, 2 in the 3rd round, and 3 in the 5th round. He earns PP for them, and discards them. NOTE: If a player chooses more than 1 Crown’s Request of the same kind in the same round, he must assign different items to them (see below Urbanization for an example). The player must discard all the chosen Crown’s Requests, even if he earns 0 Prestige Points for one or more of them. ===Guild Favors=== A player can use 1 of his face-up Guild Favors at the beginning of each of his turns: * in Phase B - Character Actions (see page 9) (i.e. before he places a die or passes) and * in Phase C - Building Actions (see page 12) (i.e. before he pays the cost or receives the Pirates). He cannot use a Guild Favor if he has no Action Markers on the Building currently being resolved, because it is not his turn. To use a Guild Favor, the player flips it face-down and immediately applies its effect (see below). No Guild Favors can be used during Phases A - Round Setup, D - Maintenance, or E - The Crown’s Requests. Reminder: A player can flip face-up: * in Phase A - Round Setup, all of his Guild Favors of the same Guild as the one he chooses (see page 8). * 1 or 2 of his Guild Favors (same or different Guilds), performing the “Casa da Coroa” Building Action (see page 13). * 1 of his Guild Favors, performing the “Guild” King’s Reward, if it is in play, (see below). ===Passing=== * The player gets 2 Reals *The player gets 3 Reals ** OR earns 1 PP, and may move 1 of his Workers to any empty City spot * The player gets 4 Reals ** OR moves 1 of his Workers into the City Watch * The player gets 5 Reals ** OR moves 1 of his Ships following the usual rules ===King’s Rewards=== Various Rewards available * The player moves 1 of his Workers to any field following the usual rules * The player flips 1 of his Guild Favors face-up. * The player discards up to 3 Pirates or gets 2 Bread from the general supply. * The player moves his disc up one step in the Windmill. He does not discard the 2 Wheat. * The player earns 3 PP. The player gets 5 Reals. * The player earns 1 PP, and may move 1 of his Workers to any empty City spot. * The player moves 1 of his Workers into the City Watch 716ab4c05f43e9d848d9b76e7a1bd50a98c37a9a 1999 1998 2016-09-20T17:54:27Z Nandblock 11082 wikitext text/x-wiki == Elements of Gameplay == == Pirates == Pirates are black marks that indicate your failure to pay debts (e.g., to feed your workers or pay the cost of an action). They have no effect on your score until game end. Pirate dice are black dice placed in the City Watch, which may be used by any player to take actions in Phase B (see City Watch below). They will only give pirates to players if they fail to pay a building cost in Phase C. == City Watch == Workers placed here have two uses: * - In Phase B, send a worker from the City Watch home to make use of a pirate die. * - In Phase D, send a worker from the City Watch home to gain 4 PP. == Windmill == Your standing on the Windmill indicates how many workers on the board you can feed automatically in Phase D, without needing additional bread. In addition, you may use the windmill to take one or more free actions during a turn: DURING PHASES B, C, OR D: * - Exchange 2 goods for 1 good of a different type. (Goods are wheat, sugar, wine.) * - Move up 1 step on the Windmill by discarding 2 wheat. (If you are already on the top step, gain 1 PP instead.) DURING PHASES B OR C ONLY: * - Move down 1 step to gain 1 bread or 2 reals. (If you are already on the bottom step, lose 1 PP to take this action.) == Gameplay == == PHASE A: SETUP AND GUILD CHOICE == The four character tiles are randomly distributed among the five buildings (one remains empty each turn, as indicated by the roman numeral on its top right). 3 pirate dice are rolled and placed in the City Watch. 3 guild dice per player are rolled and placed in rows on the Guild Board. Each player in turn places their marker on a row and selects the corresponding dice and one request. If the guild symbol matches any of their guild favours they flip them face up. == PHASE B: CHARACTER ACTIONS == Following the new turn order established in Phase A, players either select a character action or pass. A character action is selected by placing on it either a guild die or (at the cost of a worker in the City Watch) a pirate die. If a guild die is used, the player also places an action marker on the building space (to be resolved in Phase C). You may activate a character with a die whose value is equal to or greater than the number of that character’s region (1, 2 or 3). You may also use a lower-numbered die by paying the difference in bread. A character may have a maximum of 1 pirate die on it, and a maximum number of dice equal to the number of players. A player may choose one of two possible character actions: - Trigger the action specific to the character. - Harvest: all fields in that region will yield one unit per worker: either wood (if they have not yet been cleared) or a crop (wheat, sugar or wine). One building each round contains no character card, so it only offers the harvest action, plus a bonus: one field is harvested twice. === Passing === To pass, a player chooses a free spot in the passing column: they may either choose to gain reals, or take the action depicted. The new turn order will be observed for the rest of the round and the beginning of the next. == PHASE C: BUILDING ACTIONS == In numerical order, building costs are resolved and additional building actions are taken. For any building with action markers on it, all its dice are rolled. The cost is (in a four-player game) 10 reals minus the sum of the guild dice. (In three or two player games, the base value is respectively 9 or 8.) If the result is negative the cost is zero. If a player has two or more markers they still pay only once. Players have two options: - Pay the cost, and take the building action (described below) - Take pirates (1 + the number on the pirate die, if there is one) == PHASE D: MAINTENANCE == Honor (City Watch): The player with the majority of workers in the City Watch may send one home to earn 4 PP. Ties do not count. Income (Colonies): One good of the appropriate type is gained for each worker in the colonies. Upkeep (Ships): Discard 1 wood (or earn 1 pirate) per ship on the board. Feeding Workers: All workers on the board must be fed. The Windmill indicates how many are automatically fed; if this is insufficient, pay 1 bread or earn 1 pirate per worker. == PHASE E: CROWN’S REQUESTS == In rounds 1, 3 and 5 players score their requests. In round 1, they may score one of their two requests; in round 3, two out of three; in round 5, all three. Scored requests, and any goods or reals used to score them, are discarded. In round 2, convertible wheat fields cleared of wood become sugar fields. In round 4, convertible sugar fields cleared of wood become wine fields. == GAME END == The game ends after 5 rounds. All goods, wood and bread are converted to reals at 1-for-1. Players then earn 1 PP per 5 reals. Players with pirates lose points as follows: the one with most pirates loses 16 PP; 2nd most, 8 pp; 3rd most, 4 pp; 4th most, 2 PP. In addition, players lose 1 PP for each pirate over 20. Highest score wins. Ties for number of pirates or for final score go to the player earliest in the turn order. ==Reference Sheet== ===Crown’s Requests=== During Phase E, each player must choose 1 of his Crown’s Requests in the 1st round, 2 in the 3rd round, and 3 in the 5th round. He earns PP for them, and discards them. NOTE: If a player chooses more than 1 Crown’s Request of the same kind in the same round, he must assign different items to them (see below Urbanization for an example). The player must discard all the chosen Crown’s Requests, even if he earns 0 Prestige Points for one or more of them. ===Guild Favors=== A player can use 1 of his face-up Guild Favors at the beginning of each of his turns: * in Phase B - Character Actions (see page 9) (i.e. before he places a die or passes) and * in Phase C - Building Actions (see page 12) (i.e. before he pays the cost or receives the Pirates). He cannot use a Guild Favor if he has no Action Markers on the Building currently being resolved, because it is not his turn. To use a Guild Favor, the player flips it face-down and immediately applies its effect (see below). No Guild Favors can be used during Phases A - Round Setup, D - Maintenance, or E - The Crown’s Requests. Reminder: A player can flip face-up: * in Phase A - Round Setup, all of his Guild Favors of the same Guild as the one he chooses (see page 8). * 1 or 2 of his Guild Favors (same or different Guilds), performing the “Casa da Coroa” Building Action (see page 13). * 1 of his Guild Favors, performing the “Guild” King’s Reward, if it is in play, (see below). ===Passing=== * The player gets 2 Reals *The player gets 3 Reals ** OR earns 1 PP, and may move 1 of his Workers to any empty City spot * The player gets 4 Reals ** OR moves 1 of his Workers into the City Watch * The player gets 5 Reals ** OR moves 1 of his Ships following the usual rules ===King’s Rewards=== Various Rewards available * The player moves 1 of his Workers to any field following the usual rules * The player flips 1 of his Guild Favors face-up. * The player discards up to 3 Pirates or gets 2 Bread from the general supply. * The player moves his disc up one step in the Windmill. He does not discard the 2 Wheat. * The player earns 3 PP. The player gets 5 Reals. * The player earns 1 PP, and may move 1 of his Workers to any empty City spot. * The player moves 1 of his Workers into the City Watch 1b1658b6db7f88212f480c67cd5c0550d52d325f 2000 1999 2016-09-21T13:53:30Z 333-blue 13923 /* PHASE B: CHARACTER ACTIONS */ wikitext text/x-wiki == Elements of Gameplay == == Pirates == Pirates are black marks that indicate your failure to pay debts (e.g., to feed your workers or pay the cost of an action). They have no effect on your score until game end. Pirate dice are black dice placed in the City Watch, which may be used by any player to take actions in Phase B (see City Watch below). They will only give pirates to players if they fail to pay a building cost in Phase C. == City Watch == Workers placed here have two uses: * - In Phase B, send a worker from the City Watch home to make use of a pirate die. * - In Phase D, send a worker from the City Watch home to gain 4 PP. == Windmill == Your standing on the Windmill indicates how many workers on the board you can feed automatically in Phase D, without needing additional bread. In addition, you may use the windmill to take one or more free actions during a turn: DURING PHASES B, C, OR D: * - Exchange 2 goods for 1 good of a different type. (Goods are wheat, sugar, wine.) * - Move up 1 step on the Windmill by discarding 2 wheat. (If you are already on the top step, gain 1 PP instead.) DURING PHASES B OR C ONLY: * - Move down 1 step to gain 1 bread or 2 reals. (If you are already on the bottom step, lose 1 PP to take this action.) == Gameplay == == PHASE A: SETUP AND GUILD CHOICE == The four character tiles are randomly distributed among the five buildings (one remains empty each turn, as indicated by the roman numeral on its top right). 3 pirate dice are rolled and placed in the City Watch. 3 guild dice per player are rolled and placed in rows on the Guild Board. Each player in turn places their marker on a row and selects the corresponding dice and one request. If the guild symbol matches any of their guild favours they flip them face up. == PHASE B: CHARACTER ACTIONS == Following the new turn order established in Phase A, players either select a character action or pass. A character action is selected by placing on it either a guild die or (at the cost of a worker in the City Watch) a pirate die. If a guild die is used, the player also places an action marker on the building space (to be resolved in Phase C). You may activate a character with a die whose value is equal to or greater than the number of that character’s region (1, 2 or 3). You may also use a lower-numbered die by paying the difference in bread. A character may have a maximum of 1 pirate die on it, and a maximum number of dice equal to the number of players. A player may choose one of two possible character actions: - Trigger the action specific to the character. - Harvest: all fields in that region will yield one unit per worker: either wood (if they have not yet been cleared) or a crop (wheat, sugar or wine). One building each round contains no character card, so it only offers the harvest action, plus a bonus: one field is harvested twice. Steward: a space to plant. Mayor: city spot. Commander: wood region. === Passing === To pass, a player chooses a free spot in the passing column: they may either choose to gain reals, or take the action depicted. The new turn order will be observed for the rest of the round and the beginning of the next. == PHASE C: BUILDING ACTIONS == In numerical order, building costs are resolved and additional building actions are taken. For any building with action markers on it, all its dice are rolled. The cost is (in a four-player game) 10 reals minus the sum of the guild dice. (In three or two player games, the base value is respectively 9 or 8.) If the result is negative the cost is zero. If a player has two or more markers they still pay only once. Players have two options: - Pay the cost, and take the building action (described below) - Take pirates (1 + the number on the pirate die, if there is one) == PHASE D: MAINTENANCE == Honor (City Watch): The player with the majority of workers in the City Watch may send one home to earn 4 PP. Ties do not count. Income (Colonies): One good of the appropriate type is gained for each worker in the colonies. Upkeep (Ships): Discard 1 wood (or earn 1 pirate) per ship on the board. Feeding Workers: All workers on the board must be fed. The Windmill indicates how many are automatically fed; if this is insufficient, pay 1 bread or earn 1 pirate per worker. == PHASE E: CROWN’S REQUESTS == In rounds 1, 3 and 5 players score their requests. In round 1, they may score one of their two requests; in round 3, two out of three; in round 5, all three. Scored requests, and any goods or reals used to score them, are discarded. In round 2, convertible wheat fields cleared of wood become sugar fields. In round 4, convertible sugar fields cleared of wood become wine fields. == GAME END == The game ends after 5 rounds. All goods, wood and bread are converted to reals at 1-for-1. Players then earn 1 PP per 5 reals. Players with pirates lose points as follows: the one with most pirates loses 16 PP; 2nd most, 8 pp; 3rd most, 4 pp; 4th most, 2 PP. In addition, players lose 1 PP for each pirate over 20. Highest score wins. Ties for number of pirates or for final score go to the player earliest in the turn order. ==Reference Sheet== ===Crown’s Requests=== During Phase E, each player must choose 1 of his Crown’s Requests in the 1st round, 2 in the 3rd round, and 3 in the 5th round. He earns PP for them, and discards them. NOTE: If a player chooses more than 1 Crown’s Request of the same kind in the same round, he must assign different items to them (see below Urbanization for an example). The player must discard all the chosen Crown’s Requests, even if he earns 0 Prestige Points for one or more of them. ===Guild Favors=== A player can use 1 of his face-up Guild Favors at the beginning of each of his turns: * in Phase B - Character Actions (see page 9) (i.e. before he places a die or passes) and * in Phase C - Building Actions (see page 12) (i.e. before he pays the cost or receives the Pirates). He cannot use a Guild Favor if he has no Action Markers on the Building currently being resolved, because it is not his turn. To use a Guild Favor, the player flips it face-down and immediately applies its effect (see below). No Guild Favors can be used during Phases A - Round Setup, D - Maintenance, or E - The Crown’s Requests. Reminder: A player can flip face-up: * in Phase A - Round Setup, all of his Guild Favors of the same Guild as the one he chooses (see page 8). * 1 or 2 of his Guild Favors (same or different Guilds), performing the “Casa da Coroa” Building Action (see page 13). * 1 of his Guild Favors, performing the “Guild” King’s Reward, if it is in play, (see below). ===Passing=== * The player gets 2 Reals *The player gets 3 Reals ** OR earns 1 PP, and may move 1 of his Workers to any empty City spot * The player gets 4 Reals ** OR moves 1 of his Workers into the City Watch * The player gets 5 Reals ** OR moves 1 of his Ships following the usual rules ===King’s Rewards=== Various Rewards available * The player moves 1 of his Workers to any field following the usual rules * The player flips 1 of his Guild Favors face-up. * The player discards up to 3 Pirates or gets 2 Bread from the general supply. * The player moves his disc up one step in the Windmill. He does not discard the 2 Wheat. * The player earns 3 PP. The player gets 5 Reals. * The player earns 1 PP, and may move 1 of his Workers to any empty City spot. * The player moves 1 of his Workers into the City Watch 7fe20b78f931089785805c9a0eadf5de6cd9e7b2 2001 2000 2016-09-21T13:56:56Z 333-blue 13923 /* PHASE B: CHARACTER ACTIONS */ wikitext text/x-wiki == Elements of Gameplay == == Pirates == Pirates are black marks that indicate your failure to pay debts (e.g., to feed your workers or pay the cost of an action). They have no effect on your score until game end. Pirate dice are black dice placed in the City Watch, which may be used by any player to take actions in Phase B (see City Watch below). They will only give pirates to players if they fail to pay a building cost in Phase C. == City Watch == Workers placed here have two uses: * - In Phase B, send a worker from the City Watch home to make use of a pirate die. * - In Phase D, send a worker from the City Watch home to gain 4 PP. == Windmill == Your standing on the Windmill indicates how many workers on the board you can feed automatically in Phase D, without needing additional bread. In addition, you may use the windmill to take one or more free actions during a turn: DURING PHASES B, C, OR D: * - Exchange 2 goods for 1 good of a different type. (Goods are wheat, sugar, wine.) * - Move up 1 step on the Windmill by discarding 2 wheat. (If you are already on the top step, gain 1 PP instead.) DURING PHASES B OR C ONLY: * - Move down 1 step to gain 1 bread or 2 reals. (If you are already on the bottom step, lose 1 PP to take this action.) == Gameplay == == PHASE A: SETUP AND GUILD CHOICE == The four character tiles are randomly distributed among the five buildings (one remains empty each turn, as indicated by the roman numeral on its top right). 3 pirate dice are rolled and placed in the City Watch. 3 guild dice per player are rolled and placed in rows on the Guild Board. Each player in turn places their marker on a row and selects the corresponding dice and one request. If the guild symbol matches any of their guild favours they flip them face up. == PHASE B: CHARACTER ACTIONS == Following the new turn order established in Phase A, players either select a character action or pass. A character action is selected by placing on it either a guild die or (at the cost of a worker in the City Watch) a pirate die. If a guild die is used, the player also places an action marker on the building space (to be resolved in Phase C). You may activate a character with a die whose value is equal to or greater than the number of that character’s region (1, 2 or 3). You may also use a lower-numbered die by paying the difference in bread. A character may have a maximum of 1 pirate die on it, and a maximum number of dice equal to the number of players. A player may choose one of two possible character actions: - Trigger the action specific to the character. - Harvest: all fields in that region will yield one unit per worker: either wood (if they have not yet been cleared) or a crop (wheat, sugar or wine). One building each round contains no character card, so it only offers the harvest action, plus a bonus: one field is harvested twice. Steward: a space to plant. Mayor: city spot. Commander: wood. Guild master: ship spot. === Passing === To pass, a player chooses a free spot in the passing column: they may either choose to gain reals, or take the action depicted. The new turn order will be observed for the rest of the round and the beginning of the next. == PHASE C: BUILDING ACTIONS == In numerical order, building costs are resolved and additional building actions are taken. For any building with action markers on it, all its dice are rolled. The cost is (in a four-player game) 10 reals minus the sum of the guild dice. (In three or two player games, the base value is respectively 9 or 8.) If the result is negative the cost is zero. If a player has two or more markers they still pay only once. Players have two options: - Pay the cost, and take the building action (described below) - Take pirates (1 + the number on the pirate die, if there is one) == PHASE D: MAINTENANCE == Honor (City Watch): The player with the majority of workers in the City Watch may send one home to earn 4 PP. Ties do not count. Income (Colonies): One good of the appropriate type is gained for each worker in the colonies. Upkeep (Ships): Discard 1 wood (or earn 1 pirate) per ship on the board. Feeding Workers: All workers on the board must be fed. The Windmill indicates how many are automatically fed; if this is insufficient, pay 1 bread or earn 1 pirate per worker. == PHASE E: CROWN’S REQUESTS == In rounds 1, 3 and 5 players score their requests. In round 1, they may score one of their two requests; in round 3, two out of three; in round 5, all three. Scored requests, and any goods or reals used to score them, are discarded. In round 2, convertible wheat fields cleared of wood become sugar fields. In round 4, convertible sugar fields cleared of wood become wine fields. == GAME END == The game ends after 5 rounds. All goods, wood and bread are converted to reals at 1-for-1. Players then earn 1 PP per 5 reals. Players with pirates lose points as follows: the one with most pirates loses 16 PP; 2nd most, 8 pp; 3rd most, 4 pp; 4th most, 2 PP. In addition, players lose 1 PP for each pirate over 20. Highest score wins. Ties for number of pirates or for final score go to the player earliest in the turn order. ==Reference Sheet== ===Crown’s Requests=== During Phase E, each player must choose 1 of his Crown’s Requests in the 1st round, 2 in the 3rd round, and 3 in the 5th round. He earns PP for them, and discards them. NOTE: If a player chooses more than 1 Crown’s Request of the same kind in the same round, he must assign different items to them (see below Urbanization for an example). The player must discard all the chosen Crown’s Requests, even if he earns 0 Prestige Points for one or more of them. ===Guild Favors=== A player can use 1 of his face-up Guild Favors at the beginning of each of his turns: * in Phase B - Character Actions (see page 9) (i.e. before he places a die or passes) and * in Phase C - Building Actions (see page 12) (i.e. before he pays the cost or receives the Pirates). He cannot use a Guild Favor if he has no Action Markers on the Building currently being resolved, because it is not his turn. To use a Guild Favor, the player flips it face-down and immediately applies its effect (see below). No Guild Favors can be used during Phases A - Round Setup, D - Maintenance, or E - The Crown’s Requests. Reminder: A player can flip face-up: * in Phase A - Round Setup, all of his Guild Favors of the same Guild as the one he chooses (see page 8). * 1 or 2 of his Guild Favors (same or different Guilds), performing the “Casa da Coroa” Building Action (see page 13). * 1 of his Guild Favors, performing the “Guild” King’s Reward, if it is in play, (see below). ===Passing=== * The player gets 2 Reals *The player gets 3 Reals ** OR earns 1 PP, and may move 1 of his Workers to any empty City spot * The player gets 4 Reals ** OR moves 1 of his Workers into the City Watch * The player gets 5 Reals ** OR moves 1 of his Ships following the usual rules ===King’s Rewards=== Various Rewards available * The player moves 1 of his Workers to any field following the usual rules * The player flips 1 of his Guild Favors face-up. * The player discards up to 3 Pirates or gets 2 Bread from the general supply. * The player moves his disc up one step in the Windmill. He does not discard the 2 Wheat. * The player earns 3 PP. The player gets 5 Reals. * The player earns 1 PP, and may move 1 of his Workers to any empty City spot. * The player moves 1 of his Workers into the City Watch 02748536cffcf08de75539cc40709ef4c5185144 2002 2001 2016-09-21T23:00:14Z 333-blue 13923 /* PHASE B: CHARACTER ACTIONS */ wikitext text/x-wiki == Elements of Gameplay == == Pirates == Pirates are black marks that indicate your failure to pay debts (e.g., to feed your workers or pay the cost of an action). They have no effect on your score until game end. Pirate dice are black dice placed in the City Watch, which may be used by any player to take actions in Phase B (see City Watch below). They will only give pirates to players if they fail to pay a building cost in Phase C. == City Watch == Workers placed here have two uses: * - In Phase B, send a worker from the City Watch home to make use of a pirate die. * - In Phase D, send a worker from the City Watch home to gain 4 PP. == Windmill == Your standing on the Windmill indicates how many workers on the board you can feed automatically in Phase D, without needing additional bread. In addition, you may use the windmill to take one or more free actions during a turn: DURING PHASES B, C, OR D: * - Exchange 2 goods for 1 good of a different type. (Goods are wheat, sugar, wine.) * - Move up 1 step on the Windmill by discarding 2 wheat. (If you are already on the top step, gain 1 PP instead.) DURING PHASES B OR C ONLY: * - Move down 1 step to gain 1 bread or 2 reals. (If you are already on the bottom step, lose 1 PP to take this action.) == Gameplay == == PHASE A: SETUP AND GUILD CHOICE == The four character tiles are randomly distributed among the five buildings (one remains empty each turn, as indicated by the roman numeral on its top right). 3 pirate dice are rolled and placed in the City Watch. 3 guild dice per player are rolled and placed in rows on the Guild Board. Each player in turn places their marker on a row and selects the corresponding dice and one request. If the guild symbol matches any of their guild favours they flip them face up. == PHASE B: CHARACTER ACTIONS == Following the new turn order established in Phase A, players either select a character action or pass. A character action is selected by placing on it either a guild die or (at the cost of a worker in the City Watch) a pirate die. If a guild die is used, the player also places an action marker on the building space (to be resolved in Phase C). You may activate a character with a die whose value is equal to or greater than the number of that character’s region (1, 2 or 3). You may also use a lower-numbered die by paying the difference in bread. A character may have a maximum of 1 pirate die on it, and a maximum number of dice equal to the number of players. A player may choose one of two possible character actions: - Trigger the action specific to the character. - Harvest: all fields in that region will yield one unit per worker: either wood (if they have not yet been cleared) or a crop (wheat, sugar or wine). One building each round contains no character card, so it only offers the harvest action, plus a bonus: one field is harvested twice. Steward: a space to plant. Mayor: city spot. Commander: ship spot. Guild master: wood. === Passing === To pass, a player chooses a free spot in the passing column: they may either choose to gain reals, or take the action depicted. The new turn order will be observed for the rest of the round and the beginning of the next. == PHASE C: BUILDING ACTIONS == In numerical order, building costs are resolved and additional building actions are taken. For any building with action markers on it, all its dice are rolled. The cost is (in a four-player game) 10 reals minus the sum of the guild dice. (In three or two player games, the base value is respectively 9 or 8.) If the result is negative the cost is zero. If a player has two or more markers they still pay only once. Players have two options: - Pay the cost, and take the building action (described below) - Take pirates (1 + the number on the pirate die, if there is one) == PHASE D: MAINTENANCE == Honor (City Watch): The player with the majority of workers in the City Watch may send one home to earn 4 PP. Ties do not count. Income (Colonies): One good of the appropriate type is gained for each worker in the colonies. Upkeep (Ships): Discard 1 wood (or earn 1 pirate) per ship on the board. Feeding Workers: All workers on the board must be fed. The Windmill indicates how many are automatically fed; if this is insufficient, pay 1 bread or earn 1 pirate per worker. == PHASE E: CROWN’S REQUESTS == In rounds 1, 3 and 5 players score their requests. In round 1, they may score one of their two requests; in round 3, two out of three; in round 5, all three. Scored requests, and any goods or reals used to score them, are discarded. In round 2, convertible wheat fields cleared of wood become sugar fields. In round 4, convertible sugar fields cleared of wood become wine fields. == GAME END == The game ends after 5 rounds. All goods, wood and bread are converted to reals at 1-for-1. Players then earn 1 PP per 5 reals. Players with pirates lose points as follows: the one with most pirates loses 16 PP; 2nd most, 8 pp; 3rd most, 4 pp; 4th most, 2 PP. In addition, players lose 1 PP for each pirate over 20. Highest score wins. Ties for number of pirates or for final score go to the player earliest in the turn order. ==Reference Sheet== ===Crown’s Requests=== During Phase E, each player must choose 1 of his Crown’s Requests in the 1st round, 2 in the 3rd round, and 3 in the 5th round. He earns PP for them, and discards them. NOTE: If a player chooses more than 1 Crown’s Request of the same kind in the same round, he must assign different items to them (see below Urbanization for an example). The player must discard all the chosen Crown’s Requests, even if he earns 0 Prestige Points for one or more of them. ===Guild Favors=== A player can use 1 of his face-up Guild Favors at the beginning of each of his turns: * in Phase B - Character Actions (see page 9) (i.e. before he places a die or passes) and * in Phase C - Building Actions (see page 12) (i.e. before he pays the cost or receives the Pirates). He cannot use a Guild Favor if he has no Action Markers on the Building currently being resolved, because it is not his turn. To use a Guild Favor, the player flips it face-down and immediately applies its effect (see below). No Guild Favors can be used during Phases A - Round Setup, D - Maintenance, or E - The Crown’s Requests. Reminder: A player can flip face-up: * in Phase A - Round Setup, all of his Guild Favors of the same Guild as the one he chooses (see page 8). * 1 or 2 of his Guild Favors (same or different Guilds), performing the “Casa da Coroa” Building Action (see page 13). * 1 of his Guild Favors, performing the “Guild” King’s Reward, if it is in play, (see below). ===Passing=== * The player gets 2 Reals *The player gets 3 Reals ** OR earns 1 PP, and may move 1 of his Workers to any empty City spot * The player gets 4 Reals ** OR moves 1 of his Workers into the City Watch * The player gets 5 Reals ** OR moves 1 of his Ships following the usual rules ===King’s Rewards=== Various Rewards available * The player moves 1 of his Workers to any field following the usual rules * The player flips 1 of his Guild Favors face-up. * The player discards up to 3 Pirates or gets 2 Bread from the general supply. * The player moves his disc up one step in the Windmill. He does not discard the 2 Wheat. * The player earns 3 PP. The player gets 5 Reals. * The player earns 1 PP, and may move 1 of his Workers to any empty City spot. * The player moves 1 of his Workers into the City Watch d4385a1bfc43103d3dc03a23107062567b4b5aaf Steps to create a BGA game 0 117 2003 1818 2016-09-25T16:15:18Z Thrym 14216 wikitext text/x-wiki Here's a summary of the different steps you would follow when developing a game with BGA Studio. {| class="wikitable" |- ! Step !! How to reach this step !! What happened during the step? |- | Initial || [[How to join BGA developer team?]] || You can choose to join an existing team / create a new project |- | Assigned || You choose a game || You can start the development of the game |- | Pre-alpha || You've started to write some piece of code || You develop the game. During this phase, we can assist you with the framework and give you some pieces of advice. |- | Alpha || You tell us that your development is finished || "BGA review": we are reviewing your game and check if it respects [http://fr.slideshare.net/boardgamearena/bga-studio-guidelines BGA guidelines]. If not, we will ask you (and help you) to fix them. |- | Private beta || We give a "go" || "Publisher review": On preproduction platform, the publisher, the designer, we and you can test the game together and separately. We help you to take into account remarks from the publisher and the designer. |- | Public beta || The adaptation is approved by the publisher || We find together a good launch date for the game, we announce the game on BGA news, and then player can start to play! During the first days, it is common that some bugs are reported by players, and you can fix them following the instructions in [[Post-release phase]]. |- | Gold || The game is stable on BGA || Congrats! You can still modify and optimize things following the instructions in [[Post-release phase]]. |} 1224acccb4efc1797953bc5521b7f491d1704606 Gamehelpmadeira 0 231 2004 2002 2016-09-27T11:25:24Z 333-blue 13923 /* Windmill */ wikitext text/x-wiki == Elements of Gameplay == == Pirates == Pirates are black marks that indicate your failure to pay debts (e.g., to feed your workers or pay the cost of an action). They have no effect on your score until game end. Pirate dice are black dice placed in the City Watch, which may be used by any player to take actions in Phase B (see City Watch below). They will only give pirates to players if they fail to pay a building cost in Phase C. == City Watch == Workers placed here have two uses: * - In Phase B, send a worker from the City Watch home to make use of a pirate die. * - In Phase D, send a worker from the City Watch home to gain 4 PP. == Windmill == Your standing on the Windmill indicates how many workers on the board you can feed automatically in Phase D, without needing additional bread. In addition, you may use the windmill to take one or more free actions during a turn: *DURING PHASES B, C, OR D ** Exchange 2 goods for 1 good of a different type. (Goods are wheat, sugar, wine.) ** Move up 1 step on the Windmill by discarding 2 wheat. (If you are already on the top step, gain 1 PP instead.) *DURING PHASES B OR C ONLY ** Move down 1 step to gain 1 bread or 3 reals. ***If you are already on the bottom step, lose 1 PP to take this action. ****Gaining only 1 bread or 1 real. == Gameplay == == PHASE A: SETUP AND GUILD CHOICE == The four character tiles are randomly distributed among the five buildings (one remains empty each turn, as indicated by the roman numeral on its top right). 3 pirate dice are rolled and placed in the City Watch. 3 guild dice per player are rolled and placed in rows on the Guild Board. Each player in turn places their marker on a row and selects the corresponding dice and one request. If the guild symbol matches any of their guild favours they flip them face up. == PHASE B: CHARACTER ACTIONS == Following the new turn order established in Phase A, players either select a character action or pass. A character action is selected by placing on it either a guild die or (at the cost of a worker in the City Watch) a pirate die. If a guild die is used, the player also places an action marker on the building space (to be resolved in Phase C). You may activate a character with a die whose value is equal to or greater than the number of that character’s region (1, 2 or 3). You may also use a lower-numbered die by paying the difference in bread. A character may have a maximum of 1 pirate die on it, and a maximum number of dice equal to the number of players. A player may choose one of two possible character actions: - Trigger the action specific to the character. - Harvest: all fields in that region will yield one unit per worker: either wood (if they have not yet been cleared) or a crop (wheat, sugar or wine). One building each round contains no character card, so it only offers the harvest action, plus a bonus: one field is harvested twice. Steward: a space to plant. Mayor: city spot. Commander: ship spot. Guild master: wood. === Passing === To pass, a player chooses a free spot in the passing column: they may either choose to gain reals, or take the action depicted. The new turn order will be observed for the rest of the round and the beginning of the next. == PHASE C: BUILDING ACTIONS == In numerical order, building costs are resolved and additional building actions are taken. For any building with action markers on it, all its dice are rolled. The cost is (in a four-player game) 10 reals minus the sum of the guild dice. (In three or two player games, the base value is respectively 9 or 8.) If the result is negative the cost is zero. If a player has two or more markers they still pay only once. Players have two options: - Pay the cost, and take the building action (described below) - Take pirates (1 + the number on the pirate die, if there is one) == PHASE D: MAINTENANCE == Honor (City Watch): The player with the majority of workers in the City Watch may send one home to earn 4 PP. Ties do not count. Income (Colonies): One good of the appropriate type is gained for each worker in the colonies. Upkeep (Ships): Discard 1 wood (or earn 1 pirate) per ship on the board. Feeding Workers: All workers on the board must be fed. The Windmill indicates how many are automatically fed; if this is insufficient, pay 1 bread or earn 1 pirate per worker. == PHASE E: CROWN’S REQUESTS == In rounds 1, 3 and 5 players score their requests. In round 1, they may score one of their two requests; in round 3, two out of three; in round 5, all three. Scored requests, and any goods or reals used to score them, are discarded. In round 2, convertible wheat fields cleared of wood become sugar fields. In round 4, convertible sugar fields cleared of wood become wine fields. == GAME END == The game ends after 5 rounds. All goods, wood and bread are converted to reals at 1-for-1. Players then earn 1 PP per 5 reals. Players with pirates lose points as follows: the one with most pirates loses 16 PP; 2nd most, 8 pp; 3rd most, 4 pp; 4th most, 2 PP. In addition, players lose 1 PP for each pirate over 20. Highest score wins. Ties for number of pirates or for final score go to the player earliest in the turn order. ==Reference Sheet== ===Crown’s Requests=== During Phase E, each player must choose 1 of his Crown’s Requests in the 1st round, 2 in the 3rd round, and 3 in the 5th round. He earns PP for them, and discards them. NOTE: If a player chooses more than 1 Crown’s Request of the same kind in the same round, he must assign different items to them (see below Urbanization for an example). The player must discard all the chosen Crown’s Requests, even if he earns 0 Prestige Points for one or more of them. ===Guild Favors=== A player can use 1 of his face-up Guild Favors at the beginning of each of his turns: * in Phase B - Character Actions (see page 9) (i.e. before he places a die or passes) and * in Phase C - Building Actions (see page 12) (i.e. before he pays the cost or receives the Pirates). He cannot use a Guild Favor if he has no Action Markers on the Building currently being resolved, because it is not his turn. To use a Guild Favor, the player flips it face-down and immediately applies its effect (see below). No Guild Favors can be used during Phases A - Round Setup, D - Maintenance, or E - The Crown’s Requests. Reminder: A player can flip face-up: * in Phase A - Round Setup, all of his Guild Favors of the same Guild as the one he chooses (see page 8). * 1 or 2 of his Guild Favors (same or different Guilds), performing the “Casa da Coroa” Building Action (see page 13). * 1 of his Guild Favors, performing the “Guild” King’s Reward, if it is in play, (see below). ===Passing=== * The player gets 2 Reals *The player gets 3 Reals ** OR earns 1 PP, and may move 1 of his Workers to any empty City spot * The player gets 4 Reals ** OR moves 1 of his Workers into the City Watch * The player gets 5 Reals ** OR moves 1 of his Ships following the usual rules ===King’s Rewards=== Various Rewards available * The player moves 1 of his Workers to any field following the usual rules * The player flips 1 of his Guild Favors face-up. * The player discards up to 3 Pirates or gets 2 Bread from the general supply. * The player moves his disc up one step in the Windmill. He does not discard the 2 Wheat. * The player earns 3 PP. The player gets 5 Reals. * The player earns 1 PP, and may move 1 of his Workers to any empty City spot. * The player moves 1 of his Workers into the City Watch 9dc25c983600d50c15654a6b8c972fd8407363ad Gamehelphive 0 167 2005 1777 2016-09-29T00:55:40Z Saizai 9917 fix pillbug format wikitext text/x-wiki Each turn, you may either place an insect or move an insect. All insects in play must be contiguous at all times. The first player's Queen Bee to be surrounded on all sides loses. You must place your Queen Bee by your fourth turn. Tournament opening rule: You cannot place your queen as your first move. Movement rules: * Queen Bee: Can only move one space * Beetle: Only one space, but it can move on top of another insect * Spider: 3 spaces in one direction * Grasshopper: Moves to the next open space in a straight line * Soldier Ant: It can move an unlimited amount along outside borders Expansion Pieces: * Mosquito: Uses the movement ability of any piece it is touching * Ladybug: Travels two spaces on top of other pieces and one space back down * Pill bug: Can move a single space, or move a piece* currently adjacent to it to another adjacent location *: The pill bug isn't allowed to move the piece that just moved. Also, the piece that the pill bug moves isn't allowed to move on the very next turn This is just a brief summary of movement rules. This has a comprehensive overview of movement rules: http://boardgamegeek.com/thread/371756/hive-detailed-review 8632d316b0677770c343d36c11af4bff0d76da35 Gamehelpbelote 0 232 2006 2016-10-02T15:55:07Z Nanaki404 4369 Created page with "Belote is one of the most popular card game in France. It is a 2vs2 trick-taking game, played with a 32 card deck (7, 8, 9, 10, J, Q, K, A for each 4 suits). Teammates are n..." wikitext text/x-wiki Belote is one of the most popular card game in France. It is a 2vs2 trick-taking game, played with a 32 card deck (7, 8, 9, 10, J, Q, K, A for each 4 suits). Teammates are not allowed to communicate during the game, so '''please be fair and do not share information with your partner'''. == Overview == Belote usually plays in several ''hands'', up until one team reach a total score of at least 1000. Unlike most game, it is also played '''counter-clockwise'''. Each hand is played in two phases, a bidding phase and a playing phase. During the bidding phase (see Bidding for more details), the players will determine one suit (Heart, Spade, Diamond, or Club) to be the '''trump''' suit for this hand. During the playing phase, each player plays a card, one after the other. The player who played the strongest card wins the trick, and the 4 cards are added to the team points for this hand. This player then starts the next trick. == Points and card order == A trump card is always stronger than a non-trump card. Card order and points are different if this card is trump or not. {| border="1" cellspacing="1" cellpadding="3" style="border-collapse: collapse; text-align: center;" |+ Non-Trump cards |- ! | Rank || A || 10 || K || Q || J || 9 || 8 || 7 |- ! | Points | 11 || 10 || 4 || 3 || 2 || 0 || 0 || 0 |} {| border="1" cellspacing="1" cellpadding="3" style="border-collapse: collapse; text-align: center;" |+ Trump cards |- ! | Rank || J || 9 || A || 10 || K || Q || 8 || 7 |- ! | Points | 20 || 14 || 11 || 10 || 4 || 3 || 0 || 0 |} == Bidding == Each player starts this phase with 5 cards in hand, and will receive additional cards to reach 8 at the end of this phase. One card (out of the remaining 12) is made visible to all players. Starting from the player to the right of the dealer, players are given the choice to take the revealed card, or not. If one player takes it, the bidding ends, and the suit of this card becomes the '''Trump''' for this hand. If all 4 players refuse to take the card, they are once again (in the same order) given the choice of taking this card or not. But during this second time, if a player takes this card, he can choose any suit to be '''Trump''' for this hand. If all 4 players refuse twice to take the card, then this hand is cancelled, the cards are shuffled, and the dealer changes for the next hand. == Playing == Each hand is composed of 8 tricks, during which each player will, in turn order, play a card. The player starting the first trick, is the player to the right of the dealer. Later tricks are started by the player who won the previous trick. If possible, each player must play a card sharing the suit with the first card played during this trick (also called ''leading'' suit). Moreover, if that card was a trump, the player must play a trump stronger than each trump played during this trick if possible (called ''overtrumping''). If a player does not have any card of the ''leading'' suit, and if his partner has played the strongest card in the current trick (remember that trump is stronger than non-trump), then he can play any card. If a player does not have any card of the ''leading'' suit, but his partner has not played yet, or not played the strongest card, in the current trick, then he must play a trump card if possible. Also, if another player has played a trump during this trick, he must play a stronger trump if possible (he ''overtrumps''). == Additional points == The player winning the last trick earns his team 10 additional points called '''Dix de Der'''. If a team wins all 8 tricks of a hand, they get a bonus 90 points (for a total of 252). This is called '''Capot'''. If the team containing the player who took the card during the bidding (called ''attacking team'') has less points than the other team (''defending team'') for the hand, they '''lose the contract'''. If this happens, they end up with 0 points, and the other team gets all the 162 points for this hand. If both attacking team and defending team have the exact same amount of points for a hand, there is a '''Contention'''. The defending team immediately earns its points, but the points of the attacking team will be attributed to the winner of the next hand. == Belote Rebelote == During a hand, if a player has both the Queen and the King of the trump suit, he has what is called '''belote''' and '''rebelote'''. When playing one of these card, he says "Belote", and "Rebelote" for the second one, regardless of whether he starts by the Queen or the King. The corresponding team will have a bonus 20 points, in any case, even if those cards are captured by the opponents. Those 20 points are counted to know if a team ''lose the contract'' or if there is a ''contention''. But this bonus of 20 points cannot be transferred to the other team in case of contract loss, and does not prevent the other team from winning a Capot. == Remarks == This rules summary is a first draft. Please feel free to contact me if anything is unclear or poorly worded. Nanaki404 22503ab13773cc571d3e15c962c4f40d1c34f742 Game layout: view and template: yourgamename.view.php and yourgamename yourgamename.tpl 0 98 2007 1879 2016-10-07T06:58:04Z Sourisdudesert 1 /* Tips: displaying a nice button */ wikitext text/x-wiki These 2 files work together to provide the HTML layout of your game. Using these 2 files, you specify what HTML is rendered in your game client interface. In <yourgame.tpl>, you can directly write raw HTML that will be displayed by the browser. Example: extract of "hearts_hearts.tpl": <pre> <div id="myhand_wrap" class="whiteblock"> <h3>{MY_HAND}</h3> <div id="myhand"> </div> </div> </pre> == WARNING == Your view and your template are supposed to generate only the BASE layout of the game You shouldn't try to setup the current game situation in the view: this is the role of your Javascript code. Why? Because you'll have to write Javascript code to put game elements in place anyway, and you don't want to write it twice :) Example of things to generate in your view: * The overall layout of your game interface (what is displayed where). * The board and fixed elements on the board (ex: places for cards, squares, ...). Example of things that shouldn't be generate by your view: * Game elements that come and go from the game area. * Game elements that are moving from one place to another. == phplib template system == BGA is using the phplib template system, used for example in PHPbb forums. More details about how to use phplib template system here: http://www.phpbuilder.com/columns/david20000512.php3 == Variables == In your template ("tpl") file, you can use variables. Then in your view (".view.php") file, you fill these variables with value. In the example above, "{MY_HAND}" is a variable. As you can see, a variable is uppercase characters border by "{" and "}". To give a value to this variable in your view.php: Examples: <pre> // Display a translated version of "My hand" at the place of the variable in the template $this->tpl['MY_HAND'] = self::_("My hand"); // Display some raw HTML material at the place of the variable $this->tpl['MY_HAND'] = self::raw( "<div class='myhand_icon'></div>" ); </pre> WARNING: do not use a variable called {id} as it will interfere with action buttons. == Blocks == Using "blocks", you can repeat a piece of HTML from your template several time. You should use "blocks" everytime you have a block of HTML that you have to repeat a big number of time. For example, for Reversi, we have to generate 64 (8x8) squares: <pre> (in reversi_reversi.tpl) <div id="board"> <!-- BEGIN square --> <div id="square_{X}_{Y}" class="square" style="left: {LEFT}px; top: {TOP}px;"></div> <!-- END square --> <div id="discs"> </div> </div> (in reversi.view.php) $this->page->begin_block( "reversi_reversi", "square" ); $hor_scale = 64.8; $ver_scale = 64.4; for( $x=1; $x<=8; $x++ ) { for( $y=1; $y<=8; $y++ ) { $this->page->insert_block( "square", array( 'X' => $x, 'Y' => $y, 'LEFT' => round( ($x-1)*$hor_scale+10 ), 'TOP' => round( ($y-1)*$ver_scale+7 ) ) ); } } </pre> Explanations: * You specify a block in your template file, using "BEGIN" and "END" keywords. In the example above, we are creating a block named "square". * In your view, you declare your block using "begin_block" method. * Then, you can insert as many block as you want to, using "insert_block" method. The insert_block method takes 2 parameters: * the name of the block to insert. * an associative array you can use to assign values to template variables of this block. In the example above, there are 4 parameters in the block (X, Y, LEFT and TOP). == Nested blocks == You can use nested blocks. In the example below, we are going to add a mini-board for each player of the game, with 4 card places on each of it: <pre> (In template file) <!-- BEGIN player --> <div class="miniboard" id="miniboard_{PLAYER_ID}"> <div class="card_places"> <!-- BEGIN card_place --> <div id="card_place_{PLAYER_ID}_{PLACE_ID}"> </div> <!-- END card_place --> </div> </div> <!-- END player --> (In view file) $this->page->begin_block( "mygame_mygame.tpl", "card_place" ); // Nested block must be declared first $this->page->begin_block( "mygame_mygame.tpl", "player" ); foreach( $players as $player_id => $player ) { // Important: nested block must be reset here, otherwise the second player miniboard will // have 8 card_place, the third will have 12 card_place, and so one... $this->page->reset_subblocks( 'card_place' ); for( $i=1; $i<=4; $i++ ) { $this->page->insert_block( "card_place", array( 'PLAYER_ID' => $player_id, 'PLACE_ID' => $i ); } $this->page->insert_block( 'player', array( 'PLAYER_ID' => $player_id ); } </pre> == Javascript templates == For game elements that come and go from the game area, we suggest you to define a Javascript template. A Javascript template is defined in your template file like this: (Reversi Token from Reversi example): <pre> <script type="text/javascript"> // Templates var jstpl_disc='<div class="disc disccolor_${color}" id="disc_${xy}"></div>'; </script> </pre> Note: a section for javascript templates is already available at the end of your template skeleton file. Then, you can use this javascript template to insert this piece of HTML in your game interface, like this: <pre> dojo.place( this.format_block( 'jstpl_disc', { xy: x+''+y, color: color } ) , 'discs' ); </pre> == How to access game information from .view.php? == From your .view.php, you can access the following: === Access current player id=== <pre> global $g_user; $current_player_id = $g_user->get_id(); </pre> === Access game object === In your view file, "$this->game" contains an instance of your main game class. Example: <pre> // Access to some game elements description described in your "material.inc.php": $my_cards_types = $this->game->card_types; // Access to any (public) method defined in my .game.php file: $result = $this->game->myMethod(); </pre> == Tips: displaying a nice button == From time to time, you need to display a standard button in your interface. BGA framework provides you a standard button that you can use directly in your interface: <pre> <a href="#" id="my_button_id" class="bgabutton bgabutton_blue"><span>My blue button</span></a> </pre> <pre> <a href="#" id="my_button_id" class="bgabutton bgabutton_gray"><span>My gray button</span></a> </pre> <pre> <a href="#" id="my_button_id" class="bgabutton bgabutton_red"><span>My red button</span></a> </pre> <pre> <a href="#" id="my_button_id" class="bgabutton bgabutton_red bgabutton_big"><span>My big red button</span></a> </pre> Note: To see it in action, check for example a Coloretto game 3779bd04c83e42587b4db5f252e82cd97245ecd3 Game interface logic: yourgamename.js 0 88 2008 1946 2016-10-08T02:15:28Z Victoria la 11989 /* Scoring dialogs */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; this.isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> The third parameter of dojo.place can take various interesting value. values possibles : "replace" : (see description above). "first" : Places the node as a child of the reference node. The node is placed as the first child. "last" : Places the node as a child of the reference node. The node is placed as the last child. "before" : places the node right before the reference node. "last (value by default) " : places the node right after the reference node. "only" : replaces all children of the reference node with the node. positif integer : This parameter can be a positif integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. See also full doc on dojo.place : [http://dojotoolkit.org/reference-guide/1.7/dojo/place.] Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same as "slideToObject", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight, (opt)color )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight (optional): if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. * color: could be '''blue''' (default), '''red''' or '''gray'''. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''this.addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips '''this.removeTooltip( nodeId )''' Remove a tooltip from the DOM node. == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Multiple choice dialog === You can use this dialog to give user a choice with small amount of options: <pre> var keys = [1,5,10]; this.multipleChoiceDialog( _('How many bugs to fix?"), keys, dojo.hitch(this, function(choice) { var bugchoice = keys[choice]; console.log('dialog callback with '+bugchoice); this.ajaxcall( '/mygame/mygame/fixBugs.html', { bugs: bugchoice}, this, function( result ) {} ); })); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]] var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a <nowiki><div id='myDlgContent'></nowiki> div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> You can also use three extra attributes in the parameter array for the notification: <pre> $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table, "header" => array('str' => clienttranslate('Table header with parameter ${number}'), 'args' => array( 'number' => 3 ), ), "footer" => '<div>Some footer</div>', "closing" => clienttranslate( "Closing button label" ) ) ); </pre> *'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors). *'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names) *'''closing''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Gomoku example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. '''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 268b2f15027042929143bea7abc57abdc72149cc 2009 2008 2016-10-08T02:23:33Z Victoria la 11989 /* Subscribe to notifications */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; this.isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> The third parameter of dojo.place can take various interesting value. values possibles : "replace" : (see description above). "first" : Places the node as a child of the reference node. The node is placed as the first child. "last" : Places the node as a child of the reference node. The node is placed as the last child. "before" : places the node right before the reference node. "last (value by default) " : places the node right after the reference node. "only" : replaces all children of the reference node with the node. positif integer : This parameter can be a positif integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. See also full doc on dojo.place : [http://dojotoolkit.org/reference-guide/1.7/dojo/place.] Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same as "slideToObject", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight, (opt)color )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight (optional): if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. * color: could be '''blue''' (default), '''red''' or '''gray'''. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Pre-defined notification type === '''tableWindow''' - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring Dialogs|Scoring Dialogs]], see below. === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''this.addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips '''this.removeTooltip( nodeId )''' Remove a tooltip from the DOM node. == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Multiple choice dialog === You can use this dialog to give user a choice with small amount of options: <pre> var keys = [1,5,10]; this.multipleChoiceDialog( _('How many bugs to fix?"), keys, dojo.hitch(this, function(choice) { var bugchoice = keys[choice]; console.log('dialog callback with '+bugchoice); this.ajaxcall( '/mygame/mygame/fixBugs.html', { bugs: bugchoice}, this, function( result ) {} ); })); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]] var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a <nowiki><div id='myDlgContent'></nowiki> div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> You can also use three extra attributes in the parameter array for the notification: <pre> $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table, "header" => array('str' => clienttranslate('Table header with parameter ${number}'), 'args' => array( 'number' => 3 ), ), "footer" => '<div>Some footer</div>', "closing" => clienttranslate( "Closing button label" ) ) ); </pre> *'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors). *'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names) *'''closing''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Gomoku example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. '''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> 725ee481f84c6a99749fcdc5eb954415d1a9c009 2010 2009 2016-10-08T02:41:46Z Victoria la 11989 /* Notifications */ wikitext text/x-wiki This is the main file for your game interface. Here you will define: * which actions on the page will generate calls to the server * what happens when you get a notification for change from the server and how it will show in the browser. == File structure == The details on how the file is structured is described directly with comments on the code skeleton provided to you. Basically, here's this structure: * constructor: here you can define variable global to your whole interface. * setup: this method is called when the page is refreshed, in order you can setup the game interface. * onEnteringState: the method is called when entering in a new game state. This way you can customize the view for this game state. * onLeavingState: the method is called when leaving a game state. * onUpdateActionButtons: called when entering in a new state, in order you can add action buttons in status bar. * (utility methods): at this place you can define your utility methods * (player's actions): at this place you can write your handlers for player's action on the interface (ex: click on an item). * setupNotifications: in this method you associate notifications with notification handlers. This way, for each game notification, you trigger a javascript method to handle it and update the game interface. * (notification handlers): at this place you can define your notifications handlers. == General tips == ; this.player_id : Id of the player on whose browser the code is running. ; this.isSpectator : Flag set to true if the user at the table is a spectator (not a player). : Note: if you want to hide some element for spectators, you'd better use [[Game_interface_stylesheet:_yourgamename.css#spectatorMode|CSS 'spectatorMode' class]]. ; this.gamedatas : Contains your initial set of datas to init the game, created at game start or game refresh (F5) : You can update it as needed to keep an up to date reference of the game on the client side if you need it (most of the time you don't). ; this.isCurrentPlayerActive() : Returns true if the player on whose browser the code is running is currently active (it's his turn to play) ; this.getActivePlayerId() : Return the ID of active player, or null if we are not in a "activeplayer" type state. ; this.getActivePlayers() : Return an array with the IDs of players that are currently active (or an empty array if there is not). == Dojo framework == BGA is using the [http://dojotoolkit.org/ Dojo Javascript framework]. The Dojo framework allows us to do complex things easier, and the BGA framework is using Dojo framework a lot. To realize game although, you only need to use a few part of the Dojo framework. All the Dojo methods you need to use are describe on this page. == Access and manipulate the DOM == '''$('some_html_element_id')''' The $() function is used to get some HTML element using its "id" attribute. Example 1: modify the content of a "span" element: <pre> In your HTML code: <span id="a_value_in_the_game_interface">1234</span> In your Javascript code: $('a_value_in_the_game_interface').innerHTML = "9999"; </pre> Note: $() is the standard method to access some HTML element with BGA Framework. You must not use "getElementById" function. '''dojo.style''' With dojo.style you can modify a CSS property of any HTML element of your interface. Examples: <pre> // Make an element disappear dojo.style( 'my_element', 'display', 'none' ); // Give an element a 2px border dojo.style( 'my_element', 'borderWidth', '2px' ); // Change the background position of an element // (very practical when you are using CSS sprite to transform an element to another) dojo.style( 'my_element', 'backgroundPosition', '-20px -50px' ); </pre> Note: you must always use dojo.style to modify CSS properties of HTML elements. Note²: if you have to modify several CSS properties of an element, or if you have some complex CSS transformation to do, you should consider using dojo.addClass/dojo.removeClass (see below). '''dojo CSS classes manipulation''' In many situation, a bunch of many small CSS property update can be replaced by a CSS class change (ie: you add a CSS class to your element instead of applying all modification manually). Advantages are: * All your CSS stuff remains in your CSS file. * You can add/remove a list of CSS modifications with a simple function and whithout error. * You can test if you applied the stuff to an element with "dojo.hasClass" method. Example from "Reversi": <pre> // We add "possibleMove" to an element dojo.addClass( 'square_'+x+'_'+y, 'possibleMove' ); // In our CSS file, the class is defined as: .possibleMove { background-color: white; opacity: 0.2; filter:alpha(opacity=20); /* For IE8 and earlier */ cursor: pointer; } // So we've applied 4 CSS property change in one line of code. // ... and when we need to check if a square is a possible move on client side: if( dojo.hasClass( 'square_'+x+'_'+y, 'possibleMove' ) ) { ... } // ... and if we want to remove all possible moves in one line of code (see "dojo.query" method): dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); </pre> Conclusion: we encourage you to use dojo.addClass, dojo.removeClass and dojo.hasClass to make your life easier :) '''dojo.query''' With dojo.query, you can query a bunch of HTML elements with a single function, with a "CSS selector" style. Example: <pre> // All elements with class "possibleMove": var elements = dojo.query( '.possibleMove' ); // Count number of tokens (ie: elements with class "token") on the board (ie: element with id "board"): dojo.query( '#board .token' ).length; </pre> But what is really cool with dojo.query is that you can combine it with almost all methods above. Examples: <pre> // Trigger a method when the mouse enter in any element with class "meeple": dojo.query( '.meeple' ).connect( 'onmouseenter', this, 'myMethodToTrigger' ); // Hide all meeples who are on the board dojo.query( '#board .meeple' ).style( 'display', 'none' ); </pre> '''dojo.place''' dojo.place is the best function to insert some HTML code somewhere in your game interface without breaking something. It is much better to use that "innerHTML=''" method as soon as you must insert HTML tags and not only values. <pre> // Insert your HTML code as a child of a container element dojo.place( "<your html code>", "your_container_element_id" ); // Replace the container element with your new html dojo.place( "<your html code>", "your_container_element_id", "replace" ); </pre> The third parameter of dojo.place can take various interesting value. values possibles : "replace" : (see description above). "first" : Places the node as a child of the reference node. The node is placed as the first child. "last" : Places the node as a child of the reference node. The node is placed as the last child. "before" : places the node right before the reference node. "last (value by default) " : places the node right after the reference node. "only" : replaces all children of the reference node with the node. positif integer : This parameter can be a positif integer. In this case, the node will be placed as a child of the reference node with this number (counting from 0). If the number is more than number of children, the node will be appended to the reference node making it the last child. See also full doc on dojo.place : [http://dojotoolkit.org/reference-guide/1.7/dojo/place.] Usually, when you want to insert some piece of HTML in your game interface, you should use "[[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]]". '''addStyleToClass: function( cssClassName, cssProperty, propertyValue )''' Same as dojo.style(), but for all the nodes set with the specified cssClassName === Animations === '''Dojo Animations''' BGA animations is based on Dojo Animation ([http://dojotoolkit.org/documentation/tutorials/1.8/animation/ see tutorial here]). However, most of the time, you can just use methods below, which are built on top of Dojo Animation. Note: one interesting method from Dojo that could be useful from time to time is "Dojo.Animation". It allows you to make any CSS property "slide" from one value to another. '''this.slideToObject( mobile_obj, target_obj, duration, delay )''' You can use slideToObject to "slide" an element to a target position. Sliding element on the game area is the recommended and the most used way to animate your game interface. Using slides allow players to figure out what is happening on the game, as if they were playing with the real boardgame. The parameters are: * mobile_obj: the ID of the object to move. This object must be "relative" or "absolute" positioned. * target_obj: the ID of the target object. This object must be "relative" or "absolute" positioned. Note that it is not mandatory that mobile_obj and target_obj have the same size. If their size are different, the system slides the center of mobile_obj to the center of target_obj. * duration: (optional) defines the duration in millisecond of the slide. The default is 500 milliseconds. * delay: (optional). If you defines a delay, the slide will start only after this delay. This is particularly useful when you want to slide several object from the same position to the same position: you can give a 0ms delay to the first object, a 100ms delay to the second one, a 200ms delay to the third one, ... this way they won't be superposed during the slide. BE CAREFUL: The method returns an dojo.fx animation, so you can combine it with other animation if you want to. It means that you have to call the "play()" method, otherwise the animation WON'T START. Example: <pre> this.slideToObject( "some_token", "some_place_on_board" ).play(); </pre> '''this.slideToObjectPos( mobile_obj, target_obj, target_x, target_y, duration, delay )''' This method does exactly the same as "slideToObject", except than you can specify some (x,y) coordinates. This way, "mobile_obj" will slide to the specified x,y position relatively to "target_obj". Example: slide a token to some place on the board, 10 pixels to the bottom: <pre> this.slideToObjectPos( "some_token", "some_place_on_board", 0, 10 ).play(); </pre> '''this.slideTemporaryObject( mobile_obj_html, mobile_obj_parent, from, to, duration, delay )''' This method is useful when you want to slide a temporary HTML object from one place to another. As this object does not exists before the animation and won't remain after, it could be complex to create this object (with dojo.place), to place it at its origin (with placeOnObject) to slide it (with slideToObject) and to make it disappear at the end. slideTemporaryObject does all of this for you: * mobile_obj_html is a piece of HTML code that represent the object to slide. * mobile_obj_parent is the ID of an HTML element of your interface that will be the parent of this temporary HTML object. * from is the ID of the origin of the slide. * to is the ID of the target of the slide. * duration/delay works exactly like in "slideToObject" Example: <pre> this.slideTemporaryObject( '<div class="token_icon"></div>', 'tokens', 'my_origin_div', 'my_target_div' ); </pre> '''this.slideToObjectAndDestroy: function( node, to, time, delay )''' This method is a handy shortcut to slide an existing HTML object to some place then destroy it upon arrival. It can be used for example to move a victory token or a card from the board to the player panel to show that the player earns it, then destroy it when we don't need to keep it visible on the player panel. It works the same as this.slideToObject and takes the same arguments. Example: <pre> this.slideToObjectAndDestroy( "some_token", "some_place_on_board", 1000, 0 ); </pre> '''this.fadeOutAndDestroy( node )''' This function fade out the target HTML node, then destroy it. Example: <pre> this.fadeOutAndDestroy( "a_card_that_must_disappear" ); </pre> CAREFUL: the HTML node still exists until during few milliseconds, until the fadeOut has been completed. '''Rotating elements''' You can check here [http://jimfulton.info/demos/dojo-animated-rotate.html an example of use] of Dojo to make an element rotate. This example combines "Dojo.Animation" method and a CSS3 property that allow you to rotate the element. IMPORTANT: to asses browser compatibility, you must select the CSS property to use just like in the example (see sourcecode below): <pre> var transform; dojo.forEach( ['transform', 'WebkitTransform', 'msTransform', 'MozTransform', 'OTransform'], function (name) { if (typeof dojo.body().style[name] != 'undefined') { transform = name; } }); // ... and then use "transform" as the name of your CSS property for rotation </pre> === Moving elements === '''this.placeOnObject( mobile_obj, target_obj )''' placeOnObject works exactly like "slideToObject", except that the effect is immediate. This is not really an animation, but placeOnObject is frequently used before starting an animation. Example: <pre> // (We just created an object "my_new_token") // Place the new token on current player board this.placeOnObject( "my_new_token", "overall_player_board_"+this.player_id ); // Then slide it to its position on the board this.slideToObject( "my_new_token", "a_place_on_board" ).play(); </pre> '''this.placeOnObjectPos( mobile_obj, target_obj, target_x, target_y )''' This method works exactly like placeOnObject, except than you can specify some (x,y) coordinates. This way, "mobile_obj" will be placed to the specified x,y position relatively to "target_obj". '''this.attachToNewParent( mobile_obj, target_obj )''' With this method, you change the HTML parent of "mobile_obj" element. "target_obj" is the new parent of this element. The beauty of attachToNewParent is that the mobile_obj element DOES NOT MOVE during this process. Note: what happens is that the method calculate a relative position of mobile_obj to make sure it does not move after the HTML parent changes. Why using this method? Changing the HTML parent of an element can be useful for the following reasons: * When the HTML parent moves, all its child are moving with them. If some game elements is no more linked with a parent HTML object, you may want to attach it to another place. * The z_order (vertical order of display) depends on the position in the DOM, so you may need to change the parent of some game elements when they are moving in your game area. CAREFUL: when you attach an HTML element with a new parent, you break all references to this HTML element (ex: dojo.connect). == Players input == '''dojo.connect''' Used to associate a player event with one of your notification method. Example: associate a click on an element ("my_element") with one of our method ("onClickOnMyElement"): <pre> dojo.connect( $('my_element'), 'onclick', this, 'onClickOnMyElement' ); </pre> Note: this is the only possible correct way to associate a player input event to your code, and you must not use anything else. '''this.checkAction( "my_action_name" )''' Usage: checkAction: function( action, nomessage ) Check if player can do the specified action by taking into account: * current game state * interface locking (a player can't do any action if an action is already in progress) return true if action is authorized (ie: the action is listed as a "possibleaction" in current game state). return false and display an error message if not (display no message if nomessage parameter is true). The displayed error message could be either "This move is not allowed at this moment" or "An action is already in progress". Example: <pre> function onClickOnGameElement( evt ) { if( this.checkAction( "my_action" ) ) { // Do the action } } </pre> '''this.ajaxcall( url, parameters, obj_callback, callback, callback_error )''' This method must be used to send a player input to the game server. * url: the url of the action to perform. For a game, it must be: "/<mygame>/<mygame>/myAction.html" * parameters: an array of parameter to send to the game server. Note that "lock:true" must always be specified in this list of parameter in order the interface can be locked during the server call. * obj_callback: must be set to "this". * callback: a function to trigger when the server returns and everything went fine. * callback_error: (optional and rarely used) a function to trigger when the server returns an error. Usage: <pre> this.ajaxcall( '/mygame/mygame/myaction.html', { lock: true, arg1: myarg1, arg2: myarg2, ... }, this, function( result ) { // Do some stuff after a successful call } ); </pre> Restricted arguments names (please don't use them): * "action" * "module" * "class" '''this.confirmationDialog()''' Display a confirmation dialog with a yes/no choice. We advice you to NOT use this function unless the player action is really critical and could ruins the game, because it slows down the game and upset players. Usage: this.confirmationDialog( "Question to displayed", callback_function_if_click_on_yes ); Example: <pre> this.confirmationDialog( _('Are you sure to use this bonus (points penalty at the end of the game) ?'), dojo.hitch( this, function() { this.ajaxcall( '/seasons/seasons/useBonus.html', { id:bonus_id, lock:true }, this, function( result ) {} ); } ) ); </pre> ; addEventToClass: function( cssClassName, eventName, functionName ) : Same as dojo.connect(), but for all the nodes set with the specified cssClassName '''this.addActionButton( id, label, method, (opt)depreciated, (opt)bHighlight, (opt)color )''' You can use this method to add an action button in the main action status bar. Arguments: * id: a ID that should be unique in your HTML DOM document. * label: the text of the button. Should be translatable (use _() function). * method: the name of your method that must be triggered when the player clicks on this button. * depreciated (optional): do not use this. Please not specify this argument or use "null". * bHighlight (optional): if set to "true", the button is going blink to catch player's attention. Please don't abuse of blinking button. * color: could be '''blue''' (default), '''red''' or '''gray'''. You should only use this method in your "onUpdateActionButtons" method. Usually, you use it like this (from Hears example): <pre> onUpdateActionButtons: function( stateName, args ) { console.log( 'onUpdateActionButtons: '+stateName ); if( this.isCurrentPlayerActive() ) { switch( stateName ) { case 'giveCards': this.addActionButton( 'giveCards_button', _('Give selected cards'), 'onGiveCards' ); break; } } }, </pre> In the example above, we are adding a "Give selected cards" button in the case we are on game state "giveCards". When player clicks on this button, it triggers our "onGiveCards" method. == Translations == See [[Translations]] == Notifications == When something happens on the server side, your game interface Javascript logic received a notification. Here's how you can handle these notifications on the client side. === Subscribe to notifications === Your Javascript "setupNotifications" method is the place where you can subscribe to notifications from your PHP code. Here's how you associate one of your Javascript method to a notification "playDisc" (from Reversi example): <pre> // In setupNotifications method: dojo.subscribe( 'playDisc', this, "notif_playDisc" ); </pre> Note: the "playDisc" corresponds to the name of the notification you define it in your PHP code, in your "notifyAllPlayers" or "notifyPlayer" method. Then, you have to define your "notif_playDisc" method: <pre> notif_playDisc: function( notif ) { // Remove current possible moves (makes the board more clear) dojo.query( '.possibleMove' ).removeClass( 'possibleMove' ); this.addDiscOnBoard( notif.args.x, notif.args.y, notif.args.player_id ); }, </pre> In a notification handler like our "notif_playDisc" method, you can access to all notifications arguments with "notif.args". Example: <pre> // If you did this on PHP side: self::notifyAllPlayers( "myNotification", '', array( "myArgument" => 3 ) ); // On Javascript side, you can access the "myArgument" like this: notif_myNotification: function( notif ) { alert( "myArgument = " + notif.args.myArgument ); } </pre> === Synchronous notifications === When several notifications are received by your game interface, these notifications are processed immediately, one after the other, in the same exact order they have been generated in your PHP game logic. However, sometimes, you need to give some time to the players to figure out what happened on the game before jumping to the next notification. Indeed, in many games, they are a lot of automatic actions, and the computer is going to resolve all these actions very fast if you don't tell it not to do so. As an example, for Reversi, when someone is playing a disc, we want to wait 500 milliseconds before doing anything else in order the opponent player can figure out what move has been played. Here's how we do this, right after our subscription: <pre> dojo.subscribe( 'playDisc', this, "notif_playDisc" ); this.notifqueue.setSynchronous( 'playDisc', 500 ); // Wait 500 milliseconds after executing the playDisc handler </pre> === Pre-defined notification types === '''tableWindow''' - This defines notification to display [[Game_interface_logic:_yourgamename.js#Scoring_dialogs|Scoring Dialogs]], see below. '''message''' - This defines notification that shows on players log and have no other effect // You can call this on php side without doing anything on client side self::notifyAllPlayers( 'message', 'hello', array( ) ); == Tooltips == '''this.addTooltip( nodeId, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to the DOM node. Specify 'helpString' to display some information about "what is this game element?". Specify 'actionString' to display some information about "what happens when I click on this element?". You must specify both helpString and actionString. Most of the time, you use only one and specify a void string ("") for the other one. Usually, _() must be used for the text to be marked for translation. "Delay" is an optional parameter. Usually, it is primarily used to specify a zero delay for some game element when the tooltip gives really important information for the game - but remember: no essential information must be placed in tooltips as they won't be displayed in some browser (see Guidelines). Example: <pre> this.addTooltip( 'cardcount', _('Number of cards in hand'), '' ); </pre> '''this.addTooltipHtml( nodeId, html, delay )''' Add an HTML tooltip to the DOM node (for more elaborate content such as presenting a bigger version of a card). '''this.addTooltipToClass( cssClass, _( helpString ), _( actionString ), delay )''' Add a simple text tooltip to all the DOM nodes set with this cssClass. IMPORTANT: all concerned nodes must have IDs to get tooltips. '''this.addTooltipHtmlToClass( cssClass, html, delay )''' Add an HTML tooltip to to all the DOM nodes set with this cssClass (for more elaborate content such as presenting a bigger version of a card). IMPORTANT: all concerned nodes must have IDs to get tooltips '''this.removeTooltip( nodeId )''' Remove a tooltip from the DOM node. == Dialogs, warning messages, confirmation dialogs, ... == === Warning messages === Sometimes, there is something important that is happening on the game and you have to make sure all players get the message. Most of the time, the evolution of the game situation or the game log is enough, but sometimes you need something more visible. Ex: someone fulfill one of the end of the game condition, so this is the last turn. '''this.showMessage( msg, type )''' showMessage shows a message in a big rectangular area on the top of the screen of current player. * "msg" is the string to display. It should be translated. * "type" can be set to "info" or "error". If set to "info", the message will be an informative message on a white background. If set to "error", the message will be an error message on a red background. Important: the normal way to inform players about the progression of the game is the game log. "showMessage" is intrusive and should not be used often. === Confirmation dialog === When an important action with a lot of consequences is triggered by the player, you may want to propose a confirmation dialog. CAREFUL: the general guidelines of BGA is to AVOID the use of confirmation dialog. Confirmation dialogs slow down the game and bother players. The players knows that they have to pay attention about each move when they are playing online. The situation where you should use a confirmation dialog are the following: * It must not happen very often during a game. * It must be linked to an action that can really "kill a game" if the player do not pay attention. * It must be something that can be done by mistake (ex: a link on the action status bar). How to display a confirmation dialog: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> === Multiple choice dialog === You can use this dialog to give user a choice with small amount of options: <pre> var keys = [1,5,10]; this.multipleChoiceDialog( _('How many bugs to fix?"), keys, dojo.hitch(this, function(choice) { var bugchoice = keys[choice]; console.log('dialog callback with '+bugchoice); this.ajaxcall( '/mygame/mygame/fixBugs.html', { bugs: bugchoice}, this, function( result ) {} ); })); </pre> === Dialogs === At first, you shouldn't use dialogs windows. BGA guidelines specify that all game elements should be displayed on the main screen. Players can eventually scroll down to see game elements they don't need to see anytime, and you may eventually create anchors to move between game area section. Of course dialogs windows are very practical, but the thing is: all players know how to scroll down, and not all players know how to show up your dialog window. In addition, when the dialog shows up, players can't access the other game components. Sometimes although, you need to display a dialog window. Here is how you do this: // Create the new dialog. You should store the handler in a member variable to access it later this.myDlg = new dijit.Dialog({ title: _("my dialog title to translate") }); // Create the HTML of my dialog. // The best practice here is to use [[Game_layout:_view_and_template:_yourgamename.view.php_and_yourgamename_yourgamename.tpl#Javascript_templates|Javascript templates]] var html = this.format_block( 'jstpl_myDialogTemplate', { arg1: myArg1, arg2: myArg2, ... } ); // Show the dialog this.myDlg.attr("content", html ); this.myDlg.show(); // Now that the dialog has been displayed, you can connect your method to some dialog elements // Example, a "close" button: dojo.connect( $('closeDlg'), 'onclick', this, function(evt){ evt.preventDefault(); this.myDlg.hide(); } ); Tip: be careful with "hide()" method to close your dialog: the dialog and its content is not completely removed from the DOM. It can cause you problems if you try to display the same dialog several times. A good practice is to wrap all the content of your dialog in a <nowiki><div id='myDlgContent'></nowiki> div element, and to call "dojo.destroy('myDlgContent')" before displaying your dialog. === Scoring dialogs === Sometimes at the end of a round you want to display a big table that details the points wins in each section of the game. Example: in Hearts game, we display at the end of each round the number of "heart" cards collected by each player, the player who collected the Queen of Spades, and the total number of points loose by each player. Scoring dialogs are managed entirely on '''PHP side''', but they are described here as their effects are visible only on client side. Displaying a scoring dialog is quite simple and is using a special notification type: "tableWindow": <pre> // on PHP side: $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table ) ); </pre> The "table" argument is a 2 dimensional PHP array that describe the table you want to display, line by line and column by column. Example: display an 3x3 array of strings <pre> $table = array( array( "one", "two", "three" ), // This is my first line array( "four", "five", "six" ), // This is my second line array( "seven", "height", "nine" ) // This is my third line ); </pre> As you can see above, in each "cell" of your array you can display a simple string value. But you can also display a complex value with a template and associated arguments like this: <pre> $table = array( array( "one", "two", array( "str" => "a string with an ${argument}", "args" => array( 'argument' => 'argument_value' ) ) ), array( "four", "five", "six" ), array( "seven", "height", "nine" ) ); </pre> This is especially useful when you want to display player names with colors. Example from "Hearts": <pre> $firstRow = array( '' ); foreach( $players as $player_id => $player ) { $firstRow[] = array( 'str' => '${player_name}', 'args' => array( 'player_name' => $player['player_name'] ), 'type' => 'header' ); } $table[] = $firstRow; </pre> You can also use three extra attributes in the parameter array for the notification: <pre> $this->notifyAllPlayers( "tableWindow", '', array( "id" => 'finalScoring', "title" => clienttranslate("Title of the scoring dialog"), "table" => $table, "header" => array('str' => clienttranslate('Table header with parameter ${number}'), 'args' => array( 'number' => 3 ), ), "footer" => '<div>Some footer</div>', "closing" => clienttranslate( "Closing button label" ) ) ); </pre> *'''header''': the content for this parameter will display before the table (also, the html will be parsed and player names will be colored according to the current game colors). *'''footer''': the content for this parameter will display after the table (no parsing for coloring the player names) *'''closing''': if this parameter is used, a button will be displayed with this label at the bottom of the popup and will allow players to close it (more easily than by clicking the top right 'cross' icon). == Update players score == Increase a player score (with a positive or negative number): <pre> this.scoreCtrl[ player_id ].incValue( score_delta ); </pre> Set a player score to a specific value: <pre> this.scoreCtrl[ player_id ].setValue( new_score ); </pre> == Players panels == === Adding stuff to player's panel === At first, create a new "JS template" string in your template (tpl) file: (from Gomoku example) <pre> var jstpl_player_board = '\<div class="cp_board">\ <div id="stoneicon_p${id}" class="gmk_stoneicon gmk_stoneicon_${color}"></div><span id="stonecount_p${id}">0</span>\ </div>'; </pre> Then, you add this piece of code in your JS file to add this template to each player panel: <pre> // Setting up player boards for( var player_id in gamedatas.players ) { var player = gamedatas.players[player_id]; // Setting up players boards if needed var player_board_div = $('player_board_'+player_id); dojo.place( this.format_block('jstpl_player_board', player ), player_board_div ); } </pre> (Note: the code above is of course from your "setup" function in your Javascript). Very often, you have to distinguish current player and others players. In this case, you just have to create another JS template (ex: jstpl_otherplayer_board) and use it when "player_id" is different than "this.player_id". === Player's panel disabling/enabling === '''this.disablePlayerPanel( player_id )''' Disable given player panel (the panel background become gray). Usually, this is used to signal that this played passes, or will be inactive during a while. Note that the only effect of this is visual. There are no consequences on the behaviour of the panel itself. '''this.enablePlayerPanel( player_id )''' Enable a player panel that has been disabled before. '''this.enableAllPlayerPanels()''' Enable all player panels that has been disabled before. == Image loading == See also [[Game_art:_img_directory]]. '''Be careful''': by default, ALL images of your img directory are loaded on a player's browser when he loads the game. For this reason, don't let in your img directory images that are not useful, otherwise it's going to slowdown the game load. '''dontPreloadImage( image_file_name )''' Using dontPreloadImage, you tell the interface to not preload a specific image in your img directory. Example of use: <pre> this.dontPreloadImage( 'cards.png' ); </pre> This is particularly useful if for example you have 2 different themes for a game. To accelerate the loading of the game, you can specify to not preload images corresponding to the other theme. Another example of use: in "Gosu" game with Kamakor extension, you play with 5 sets of cards among 10 available. Cards images are organized by sets, and we only preload the images corresponding to the 5 current sets. '''Note:''' You don't need to specify to not preload game box images (game_box.png, game_box75.png...) since they are not preloaded by default. == Other useful stuff == '''dojo.hitch''' With dojo.hitch, you can create a callback function that will run with your game object context whatever happen. Typical example: display a BGA confirmation dialog with a callback function created with dojo.hitch: <pre> this.confirmationDialog( _('Are you sure you want to make this?'), dojo.hitch( this, function() { this.ajaxcall( '/mygame/mygame/makeThis.html', { lock:true }, this, function( result ) {} ); } ) ); </pre> In the example above, using dojo.hitch, we are sure that the "this" object will be set when the callback is called. ; updateCounters(counters) : Useful for updating game counters in the player panel (such as resources). : 'counters' arg is an associative array [counter_name_value => [ 'counter_name' => counter_name_value, 'counter_value' => counter_value_value], ... ] : All counters must be referenced in this.gamedatas.counters and will be updated. : DOM objects referenced by 'counter_name' will have their innerHTML updated with 'counter_value'. == BGA GUI components == BGA framework provides some useful ready-to-use components for the game interface: [[Studio#BGA_Studio_game_components_reference]] Note that each time you are using an additional component, you must declare it at the top of your Javascript file in the list of modules used. Example if you are using "ebg.stock": <pre> define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <=== we are using ebg.stock module ], </pre> ec2dc4ab0500952928364af820b5d89651ecc3d2 Gamehelpdarkagent 0 207 2011 1757 2016-10-08T14:21:08Z Philcollins 10686 /* Equipment cards effects */ wikitext text/x-wiki == Goal and Context of DARK AGENT board game : == At the head of a secret service, you use your spy satellites (tokens of your color) to coordinate attacks on targets that you designate to your agents : - Objectives (tiger), Sentinel (gray), enemies Agents (their color), or the Dark Agent (black) you win all their victory points when capturing them and place them in front of you; - Equipment (object in a white disk), single use, are taken over to be used and discarded later; - Special actions (red with no points) Are resolved immediately and remain in place. One or more of your agents can attack a target only if your satellites lets you see both your agents and the target. When players have had them all, the number of captured target agreed early in the game (2 to 5 on the 5 available), it ends. You can add the capture of the Dark Agent as a further condition endgame. The player accumulating the most points wins. He adds the points of his agents still on the ground. Also note that each time a player wins an aim, he takes the bonus 3 PV token to its previous owner. Unplayed nations are used as neutral nations. == Permanent power of Aims == Prisoner : Once by turn, exchange place of one of your spy with an enemy (dark agent, opponent spy or sentinel) ---- Scientist : All of your spies get invulnerability ---- Nuclear deterrence : All your attacks get +2 bonus ---- Control Center : All your satellites are supers-satellites ---- Briefcase : One more vote FOR if you vote FOR the peace == Game tactics : == This game is rich of tactical and strategic possibilities. Players can take the game in hand before the first three plays. It has many strenghs : - Game duration could be calibrated (2 players / aim, the game lasts less than 10 minutes). - Play turns are smooth, even with 6 players (calibrated in duration with the number of aims to win in order to make a short/long play) - The single player mode is a real challenge and allows to understand the mechanisms. - There are many strategies and many ways to win. == Tutorials == Youtube tutorials are available : search spacereindeers, or go to [http://www.spacereindeers.com/dark-agent link DarkAgent] 2e35b14918f63ae25098168f999b296a4f2b384e 2012 2011 2016-10-08T14:21:26Z Philcollins 10686 /* Permanent power of Aims */ wikitext text/x-wiki == Goal and Context of DARK AGENT board game : == At the head of a secret service, you use your spy satellites (tokens of your color) to coordinate attacks on targets that you designate to your agents : - Objectives (tiger), Sentinel (gray), enemies Agents (their color), or the Dark Agent (black) you win all their victory points when capturing them and place them in front of you; - Equipment (object in a white disk), single use, are taken over to be used and discarded later; - Special actions (red with no points) Are resolved immediately and remain in place. One or more of your agents can attack a target only if your satellites lets you see both your agents and the target. When players have had them all, the number of captured target agreed early in the game (2 to 5 on the 5 available), it ends. You can add the capture of the Dark Agent as a further condition endgame. The player accumulating the most points wins. He adds the points of his agents still on the ground. Also note that each time a player wins an aim, he takes the bonus 3 PV token to its previous owner. Unplayed nations are used as neutral nations. == Game tactics : == This game is rich of tactical and strategic possibilities. Players can take the game in hand before the first three plays. It has many strenghs : - Game duration could be calibrated (2 players / aim, the game lasts less than 10 minutes). - Play turns are smooth, even with 6 players (calibrated in duration with the number of aims to win in order to make a short/long play) - The single player mode is a real challenge and allows to understand the mechanisms. - There are many strategies and many ways to win. == Tutorials == Youtube tutorials are available : search spacereindeers, or go to [http://www.spacereindeers.com/dark-agent link DarkAgent] 4d3696602bcbd378d95adaf2f5a5a7edac4f2067 2013 2012 2016-10-08T14:21:41Z Philcollins 10686 /* Game tactics : */ wikitext text/x-wiki == Goal and Context of DARK AGENT board game : == At the head of a secret service, you use your spy satellites (tokens of your color) to coordinate attacks on targets that you designate to your agents : - Objectives (tiger), Sentinel (gray), enemies Agents (their color), or the Dark Agent (black) you win all their victory points when capturing them and place them in front of you; - Equipment (object in a white disk), single use, are taken over to be used and discarded later; - Special actions (red with no points) Are resolved immediately and remain in place. One or more of your agents can attack a target only if your satellites lets you see both your agents and the target. When players have had them all, the number of captured target agreed early in the game (2 to 5 on the 5 available), it ends. You can add the capture of the Dark Agent as a further condition endgame. The player accumulating the most points wins. He adds the points of his agents still on the ground. Also note that each time a player wins an aim, he takes the bonus 3 PV token to its previous owner. Unplayed nations are used as neutral nations. == Tutorials == Youtube tutorials are available : search spacereindeers, or go to [http://www.spacereindeers.com/dark-agent link DarkAgent] 6232702f5a100fc56721c8c7fab002ba7828398b 2014 2013 2016-10-08T14:22:01Z Philcollins 10686 /* Tutorials */ wikitext text/x-wiki == Goal and Context of DARK AGENT board game : == At the head of a secret service, you use your spy satellites (tokens of your color) to coordinate attacks on targets that you designate to your agents : - Objectives (tiger), Sentinel (gray), enemies Agents (their color), or the Dark Agent (black) you win all their victory points when capturing them and place them in front of you; - Equipment (object in a white disk), single use, are taken over to be used and discarded later; - Special actions (red with no points) Are resolved immediately and remain in place. One or more of your agents can attack a target only if your satellites lets you see both your agents and the target. When players have had them all, the number of captured target agreed early in the game (2 to 5 on the 5 available), it ends. You can add the capture of the Dark Agent as a further condition endgame. The player accumulating the most points wins. He adds the points of his agents still on the ground. Also note that each time a player wins an aim, he takes the bonus 3 PV token to its previous owner. Unplayed nations are used as neutral nations. a92aaf1848178f91a299e77bc3e84721a71823ff 2015 2014 2016-10-08T14:43:59Z Philcollins 10686 /* Goal and Context of DARK AGENT board game : */ wikitext text/x-wiki == Goal and Context of DARK AGENT board game : == Players take the role of secret services of nations attempting to eradicate a terrorist threat, an organization known as the UTE. UTE is led by Kara, a fighter whose life was a living hell. Kara wants to control the world today. The choice no longer exists, she must be eliminated or she will destroy our way of life. Her organization has already infiltrated strategic areas: nuclear submarine, space control center, virology laboratory and the United Nations whose senior official was kidnapped. You will have to secure these places and deliver the hostage. You do not know who to trust, secret services are forced to act underground, like terrorists do. Infiltrators may be among your own services. To act underground, it will make the best use of space surveillance satellites to locate agents, targets, tactical or strategic places and control the operations. 5913bd3160a35f53c1e49fd24ced34bd8034adc2 2016 2015 2016-10-08T14:44:48Z Philcollins 10686 /* Goal and Context of DARK AGENT board game : */ wikitext text/x-wiki == Description of the game : == Players take the role of secret services of nations attempting to eradicate a terrorist threat, an organization known as the UTE. UTE is led by Kara, a fighter whose life was a living hell. Kara wants to control the world today. The choice no longer exists, she must be eliminated or she will destroy our way of life. Her organization has already infiltrated strategic areas: nuclear submarine, space control center, virology laboratory and the United Nations whose senior official was kidnapped. You will have to secure these places and deliver the hostage. You do not know who to trust, secret services are forced to act underground, like terrorists do. Infiltrators may be among your own services. To act underground, it will make the best use of space surveillance satellites to locate agents, targets, tactical or strategic places and control the operations. ebebbd8a5bd43438fee493c466a246e43a7c717a Gamehelpohhell 0 233 2017 2016-10-09T01:30:33Z Marcgenesis 10219 Created page with "'''Players and Cards''' From 3 to 7 people can play. The game is best when played with 4 to 6. A standard 52 card deck is used. The cards in each suit rank (from high to low..." wikitext text/x-wiki '''Players and Cards''' From 3 to 7 people can play. The game is best when played with 4 to 6. A standard 52 card deck is used. The cards in each suit rank (from high to low) A K Q J 10 9 8 7 6 5 4 3 2. '''Sequence of Hands''' The game consists of a series of hands. The first hand is played with 7 to 10 cards dealt to each player, depending on the number of players: 3 to 5 players, 10 cards each; 6 players, 8 cards each; 7 players, 7 cards each (because of the limit of 52 cards available). Each successive hand is played with one card fewer, down to a hand of just one card each, then one card more per hand back up to the starting level. Example: With 7 players, the hands are: 7 cards, then 6,5,4,3,2,1, then 2,3,4,5,6,7, for a total of 13 hands to the game. A game should take approximately 45 minutes. '''Object of the Game''' The object is for each player to bid the number of tricks he thinks he can take from each hand. The hook is that at least one player will fail on each hand, because the total number of tricks bid by the players may not equal the number of tricks available on that hand. '''Deal''' The turn to deal rotates clockwise with each hand. The cards are shuffled and the dealer deals the cards singly until everyone has the appropriate number of cards for the hand being played. The next card is turned face up and the suit of this card is the trump suit for the hand. The trump suit beats any of the other three suits played in that hand. The remaining undealt cards are placed in a face down stack with the turned trump on top of it. '''Bidding''' The bidding in each hand begins with the player to the left of the dealer, then continues clockwise, back around to the dealer, who bids last. Each bid is a number representing the number of tricks that player will try to take. Everyone must bid - it is not possible to pass, but you can bid zero, in which case your object is to take no tricks at all. Remember the hook: the dealer may not bid the number that would cause the total number of tricks bid to equal the number of tricks available; a hand will always be "over-bid" or "under-bid". Keep in mind when bidding that not all cards in the deck are in play in any hand. '''Play''' The play begins with the player to the dealer's left, who leads the first card. The lead may be any suit (including trump). Play follows clockwise. Each player must follow the suit led, if he can. If not, he may play any other card in his hand, including trump. The player who has played the highest trump card, or if no trump was played, the highest card of the suit led, wins the trick. That player then leads to the next trick. Continue until all tricks have been played and won. '''Scoring''' The scoring method used is to award 1 point for each trick won plus a bonus of 10 points for players who win exactly the number of tricks they bid. So for example a player who bid 2 would score 12 points for winning exactly 2 tricks, but only 1 for 1 trick and 3 for 3 tricks. This gives a player whose bid fails a slight incentive to win as many tricks as possible. de21ee49b65cac95968ed7b67b0e427206da26aa 2018 2017 2016-10-09T01:30:57Z Marcgenesis 10219 wikitext text/x-wiki '''Players and Cards''' From 3 to 7 people can play. The game is best when played with 4 to 6. A standard 52 card deck is used. The cards in each suit rank (from high to low) A K Q J 10 9 8 7 6 5 4 3 2. '''Sequence of Hands''' The game consists of a series of hands. The first hand is played with 7 to 10 cards dealt to each player, depending on the number of players: 3 to 5 players, 10 cards each 6 players, 8 cards each 7 players, 7 cards each (because of the limit of 52 cards available). Each successive hand is played with one card fewer, down to a hand of just one card each, then one card more per hand back up to the starting level. Example: With 7 players, the hands are: 7 cards, then 6,5,4,3,2,1, then 2,3,4,5,6,7, for a total of 13 hands to the game. A game should take approximately 45 minutes. '''Object of the Game''' The object is for each player to bid the number of tricks he thinks he can take from each hand. The hook is that at least one player will fail on each hand, because the total number of tricks bid by the players may not equal the number of tricks available on that hand. '''Deal''' The turn to deal rotates clockwise with each hand. The cards are shuffled and the dealer deals the cards singly until everyone has the appropriate number of cards for the hand being played. The next card is turned face up and the suit of this card is the trump suit for the hand. The trump suit beats any of the other three suits played in that hand. The remaining undealt cards are placed in a face down stack with the turned trump on top of it. '''Bidding''' The bidding in each hand begins with the player to the left of the dealer, then continues clockwise, back around to the dealer, who bids last. Each bid is a number representing the number of tricks that player will try to take. Everyone must bid - it is not possible to pass, but you can bid zero, in which case your object is to take no tricks at all. Remember the hook: the dealer may not bid the number that would cause the total number of tricks bid to equal the number of tricks available; a hand will always be "over-bid" or "under-bid". Keep in mind when bidding that not all cards in the deck are in play in any hand. '''Play''' The play begins with the player to the dealer's left, who leads the first card. The lead may be any suit (including trump). Play follows clockwise. Each player must follow the suit led, if he can. If not, he may play any other card in his hand, including trump. The player who has played the highest trump card, or if no trump was played, the highest card of the suit led, wins the trick. That player then leads to the next trick. Continue until all tricks have been played and won. '''Scoring''' The scoring method used is to award 1 point for each trick won plus a bonus of 10 points for players who win exactly the number of tricks they bid. So for example a player who bid 2 would score 12 points for winning exactly 2 tricks, but only 1 for 1 trick and 3 for 3 tricks. This gives a player whose bid fails a slight incentive to win as many tricks as possible. 9262dfb62ef682a78680ebfc0cd66ddef5879cff 2019 2018 2016-10-09T01:31:16Z Marcgenesis 10219 wikitext text/x-wiki '''Players and Cards''' From 3 to 7 people can play. The game is best when played with 4 to 6. A standard 52 card deck is used. The cards in each suit rank (from high to low) A K Q J 10 9 8 7 6 5 4 3 2. '''Sequence of Hands''' The game consists of a series of hands. The first hand is played with 7 to 10 cards dealt to each player, depending on the number of players: 3 to 5 players, 10 cards each 6 players, 8 cards each 7 players, 7 cards each (because of the limit of 52 cards available). Each successive hand is played with one card fewer, down to a hand of just one card each, then one card more per hand back up to the starting level. Example: With 7 players, the hands are: 7 cards, then 6,5,4,3,2,1, then 2,3,4,5,6,7, for a total of 13 hands to the game. A game should take approximately 45 minutes. '''Object of the Game''' The object is for each player to bid the number of tricks he thinks he can take from each hand. The hook is that at least one player will fail on each hand, because the total number of tricks bid by the players may not equal the number of tricks available on that hand. '''Deal''' The turn to deal rotates clockwise with each hand. The cards are shuffled and the dealer deals the cards singly until everyone has the appropriate number of cards for the hand being played. The next card is turned face up and the suit of this card is the trump suit for the hand. The trump suit beats any of the other three suits played in that hand. The remaining undealt cards are placed in a face down stack with the turned trump on top of it. '''Bidding''' The bidding in each hand begins with the player to the left of the dealer, then continues clockwise, back around to the dealer, who bids last. Each bid is a number representing the number of tricks that player will try to take. Everyone must bid - it is not possible to pass, but you can bid zero, in which case your object is to take no tricks at all. Remember the hook: the dealer may not bid the number that would cause the total number of tricks bid to equal the number of tricks available; a hand will always be "over-bid" or "under-bid". Keep in mind when bidding that not all cards in the deck are in play in any hand. '''Play''' The play begins with the player to the dealer's left, who leads the first card. The lead may be any suit (including trump). Play follows clockwise. Each player must follow the suit led, if he can. If not, he may play any other card in his hand, including trump. The player who has played the highest trump card, or if no trump was played, the highest card of the suit led, wins the trick. That player then leads to the next trick. Continue until all tricks have been played and won. '''Scoring''' The scoring method used is to award 1 point for each trick won plus a bonus of 10 points for players who win exactly the number of tricks they bid. So for example a player who bid 2 would score 12 points for winning exactly 2 tricks, but only 1 for 1 trick and 3 for 3 tricks. This gives a player whose bid fails a slight incentive to win as many tricks as possible. 2a418f5953ce04859a9c9a268b9ea1a679c0b6e7 2021 2019 2016-10-10T15:27:08Z Marcgenesis 10219 wikitext text/x-wiki '''Players and Cards''' From 3 to 7 people can play. The game is best when played with 4 to 6. A standard 52 card deck is used. The cards in each suit rank (from high to low) A K Q J 10 9 8 7 6 5 4 3 2. '''Sequence of Hands''' The game consists of a series of hands. The first hand is played with 7 to 10 cards dealt to each player, depending on the number of players: 3 to 5 players, 10 cards each 6 players, 8 cards each 7 players, 7 cards each (because of the limit of 52 cards available). Each successive hand is played with one card fewer, down to a hand of just one card each, then one card more per hand back up to the starting level. Example: With 7 players, the hands are: 7 cards, then 6,5,4,3,2,1, then 2,3,4,5,6,7, for a total of 13 hands to the game. A game should take approximately 45 minutes. '''Object of the Game''' The object is for each player to bid the number of tricks he thinks he can take from each hand. The hook is that at least one player will fail on each hand, because the total number of tricks bid by the players may not equal the number of tricks available on that hand. '''Deal''' The turn to deal rotates clockwise with each hand. The cards are shuffled and the dealer deals the cards singly until everyone has the appropriate number of cards for the hand being played. The next card is turned face up and the suit of this card is the trump suit for the hand. The trump suit beats any of the other three suits played in that hand. The remaining undealt cards are placed in a face down stack with the turned trump on top of it. '''Bidding''' The bidding in each hand begins with the player to the left of the dealer, then continues clockwise, back around to the dealer, who bids last. Each bid is a number representing the number of tricks that player will try to take. Everyone must bid - it is not possible to pass, but you can bid zero, in which case your object is to take no tricks at all. Remember the hook: the dealer may not bid the number that would cause the total number of tricks bid to equal the number of tricks available; a hand will always be "over-bid" or "under-bid". Keep in mind when bidding that not all cards in the deck are in play in any hand. '''Play''' The play begins with the player to the dealer's left, who leads the first card. The lead may be any suit (including trump). Play follows clockwise. Each player must follow the suit led, if he can. If not, he may play any other card in his hand, including trump. The player who has played the highest trump card, or if no trump was played, the highest card of the suit led, wins the trick. That player then leads to the next trick. Continue until all tricks have been played and won. '''Scoring''' The scoring method used is to award 1 point for each trick won plus a bonus of 10 points for players who win exactly the number of tricks they bid. So for example a player who bid 2 would score 12 points for winning exactly 2 tricks, but only 1 for 1 trick and 3 for 3 tricks. This gives a player whose bid fails a slight incentive to win as many tricks as possible. '''Variants''' Here are the different variants implemented on BGA: Game style: * Long: As described above * Long - Inverted: Instead of going 10 ... 1 ... 10 (or the equivalent according to the number of players), the hands go 1 ... 10 ... 1 * Short - Up and Down: Hands always go 6 ... 1 ... 6 * Short - Up: Hands always go 1 ... 10 * Short - Down: Hands always go 10 ... 1 Scoring style: * Positive: As described above * Neutral: 10 points + number of tricks for a successful bid. No points for a lost bid. * Negative: 10 points + number of tricks for a successful bid. -10 points per tricks under or over on a lost bid. ece05e22829736a7c7d35837c10ec5b5d2e0beff 2022 2021 2016-10-11T19:21:38Z Marcgenesis 10219 wikitext text/x-wiki '''Players and Cards''' From 3 to 7 people can play. The game is best when played with 4 to 6. A standard 52 card deck is used. The cards in each suit rank (from high to low) A K Q J 10 9 8 7 6 5 4 3 2. '''Sequence of Hands''' The game consists of a series of hands. The first hand is played with 7 to 10 cards dealt to each player, depending on the number of players: 3 to 5 players, 10 cards each 6 players, 8 cards each 7 players, 7 cards each (because of the limit of 52 cards available). Each successive hand is played with one card fewer, down to a hand of just one card each, then one card more per hand back up to the starting level. Example: With 7 players, the hands are: 7 cards, then 6,5,4,3,2,1, then 2,3,4,5,6,7, for a total of 13 hands to the game. A game should take approximately 45 minutes. '''Object of the Game''' The object is for each player to bid the number of tricks he thinks he can take from each hand. The hook is that at least one player will fail on each hand, because the total number of tricks bid by the players may not equal the number of tricks available on that hand. '''Deal''' The turn to deal rotates clockwise with each hand. The cards are shuffled and the dealer deals the cards singly until everyone has the appropriate number of cards for the hand being played. The next card is turned face up and the suit of this card is the trump suit for the hand. The trump suit beats any of the other three suits played in that hand. The remaining undealt cards are placed in a face down stack with the turned trump on top of it. '''Bidding''' The bidding in each hand begins with the player to the left of the dealer, then continues clockwise, back around to the dealer, who bids last. Each bid is a number representing the number of tricks that player will try to take. Everyone must bid - it is not possible to pass, but you can bid zero, in which case your object is to take no tricks at all. Remember the hook: the dealer may not bid the number that would cause the total number of tricks bid to equal the number of tricks available; a hand will always be "over-bid" or "under-bid". Keep in mind when bidding that not all cards in the deck are in play in any hand. '''Play''' The play begins with the player to the dealer's left, who leads the first card. The lead may be any suit (including trump). Play follows clockwise. Each player must follow the suit led, if he can. If not, he may play any other card in his hand, including trump. The player who has played the highest trump card, or if no trump was played, the highest card of the suit led, wins the trick. That player then leads to the next trick. Continue until all tricks have been played and won. '''Scoring''' The scoring method used is to award 1 point for each trick won plus a bonus of 10 points for players who win exactly the number of tricks they bid. So for example a player who bid 2 would score 12 points for winning exactly 2 tricks, but only 1 for 1 trick and 3 for 3 tricks. This gives a player whose bid fails a slight incentive to win as many tricks as possible. '''Variants''' Here are the different variants implemented on BGA: Game style: * Long: As described above * Long - Inverted: Instead of going 10 ... 1 ... 10 (or the equivalent according to the number of players), the hands go 1 ... 10 ... 1 * Short - Up and Down: Hands always go 6 ... 1 ... 6 * Short - Up: Hands always go 1 ... 10 * Short - Down: Hands always go 10 ... 1 Scoring style: * Positive: As described above * Neutral: 10 points + number of tricks for a successful bid. No points for a lost bid. * Negative: 10 points for a successful bid. -10 points per tricks under or over on a lost bid. 10dadedcfb49192dce582ee1c86176293c767a02 Gamehelpevogamenoname 0 234 2020 2016-10-10T08:48:07Z Kingcarlo 4556 Created page with "https://drive.google.com/file/d/0B5hp3Ywhg5nFMnBEY29acHVLNHc/view" wikitext text/x-wiki https://drive.google.com/file/d/0B5hp3Ywhg5nFMnBEY29acHVLNHc/view 851ae0e9a6ac7459baef5a546832c838189b207c Gamehelpdungeontwister 0 235 2023 2016-10-12T12:55:58Z Greenman 1407 Created page with "== Actions == === Reveal a Room === A room can only be revealed (turned face-up) if one of your characters has direct access to it before it is revealed (figure 2). All charac..." wikitext text/x-wiki == Actions == === Reveal a Room === A room can only be revealed (turned face-up) if one of your characters has direct access to it before it is revealed (figure 2). All characters on your starting line have direct access to the first two rooms adjacent to the starting line. So, both these rooms can be revealed for 1 AP each. Remove all the tokens on the room to be revealed. Slide the room to the side from the board’s structure, flip the room and replace it in the structure face up as indicated in figure 3. The player revealing the room first places all the tokens that were on this room except the objects matching his own color. These objects are placed by his opponent after the revealing player has placed all the other tokens. All tokens are placed face-up, no more than one per square. Each token must be placed on an empty floor square or on a Rotation Gear === Rotate a Room === Each room in the labyrinth is equipped with a complex wheels and gears mechanism allowing it to rotate. The Rotation Gear which triggers this movement is represented by a colored spinning arrow and a number within a square of each room. Such squares are called Rotation Gear. For 1 AP, a character standing on a Rotation Gear can rotate the room 1/4 of a turn in the arrow’s direction. He can spend 2 AP to rotate 1/2 of a turn, or 3 AP to rotate 3/4 of a turn, etc. All rooms are matched as colored pairs (they are also numbered for easier identification), rotating in opposite direction from each other. A character standing on the Rotation Gear #1 can also choose to remotely rotate the other room bearing the same number for 1 AP for each 1/4 of a turn. The targeted room will rotate in the direction of the arrows printed on its own board. In short, to know which way the room rotates, look at the arrow printed on the rotating room. 1 AP only allows you to rotate one room at a time! You can never rotate two rooms at the same time. To rotate a room, slide the room out of the board’s structure. Rotate the room and put it back into the structure. When a player rotates a room, he is not allowed to change his mind if the new game situation isn’t to his liking. None of the tokens in the room change place during a rotation. === Move === You can use 1 AP to move one of your own characters. The white number on the left on each character token (Speed) shows how many squares a character can move for 1 AP (for example, the Thief can move 5 squares with 1 AP). You are never forced to use all of your movement points. You can also give more than one AP to the same character in order to have it move several times, although one movement must be fully completed before another can start (first Golden Rule). ===Initiate Combat === You need to spend 1 AP to initiate Combat. A character can attack any adjacent enemy character. You cannot initiate a Combat through a closed Portcullis or a wall. Each player selects a Combat card from his hand and places it face-down in front of him. Both cards are then revealed simultaneously. Each player adds the card’s value to his character’s Combat value (black number on the right on his character token). The player with the highest total wins the Combat and the opponent’s character is wounded. Wounded characters are placed face-down. In the case of a tie, nothing happens and the player whose turn it is can decide to spend 1 new AP to initiate a new Combat. All used Combat cards are removed from the game. Gather them in a single face-down pile. Players are not allowed to look at these cards. The “Combat +0” card is the only card that the owner always gets back. The Active Player cannot attack again a character that has been wounded during this turn, even if another character did the wounding. ====Group Combat==== If more than 1 character is adjacent to one or more of his opponent’s characters, all living (unwounded) characters must participate in the Combat (see figure 4). The attacking player adds the Combat value of all his adjacent characters and the defending player does the same. Although more than one character is attacking or defending, each player only plays one Combat card for his team. When the Combat is over, all the loser’s characters involved in the combat are wounded and placed face-down. ==== Wounded characters==== When a character is wounded, the object he was carrying is left in the square with him. A wounded character cannot carry out any Actions. His Combat value is 0 but he is still permitted to play a Combat card if he is attacked during following turns. If a wounded character loses a Combat, he is removed from the game. The player who killed him removes the character token from the board and places it in front of him as proof of having earned 1 VP. A wounded character cannot attack or participate in group Combat. He can only defend himself if he is directly attacked (you can only attack one wounded character at the same time). If a wounded character wins a Combat, the attacking character or characters are wounded. === Use a Character’s Special Ability=== Most characters have one or more Special Abilities. Some of them are permanent and do not require the player to spend AP to use them; others require 1 AP to be activated. Refer to the character description to learn about each character's Special Abilities. Unless otherwise specified, a wounded character cannot use his Special Abilities, even if they are permanent Abilities. === Use an Object === Some objects also have permanent Special Effects that do not require the player to spend AP to use them; others require 1 AP to be activated. Objects with permanent Effects always stay on the board. Objects that require AP to have their Effect activated are removed from the board once they are used. A wounded character cannot use an object requiring AP activation since he is not permitted to carry out an Action. == Objects == Each character can only carry one object or one wounded character of his own color. To pick up an object or a wounded character, simply pass through or stop on the square containing it. This doesn’t require the player to spend any AP as it is part of the character’s movement. A character can also drop an object or wounded character in a square while carrying out a movement. This also does not require the player to spend any AP. But, the second Golden Rule must still be followed and no object or wounded character may be left on a Pit Trap (unless it is a Rope) or on any other forbidden square. There can never be two objects on the same square. A character moving through a square occupied by a wounded character (friendly or enemy) and an object can pick up the object for no AP. If one of your characters moves through another character of the same color, you can take, give or trade objects and/or wounded characters as you wish between the two characters. This does not cost any AP. However, at the end of any Action, the second Golden Rule must always be followed (1 character + 1 object or 1 character + 1 wounded character maximum per square). Blue characters can use and carry Yellow objects and vice versa. Objects or wounded characters are always placed underneath the token of the character carrying it. At any time, any player can look at a token underneath a character, friendly or enemy === Carrying wounded characters === Wounded characters can be carried like objects by characters of the same color. All rules applicable to objects are applicable to wounded characters. If a character carrying a wounded one loses a Combat, the wounded one is removed from the game (+1 VP for the winner) and the carrier becomes wounded himself ===Moving a Character out of the Labyrinth=== As soon as one of your characters moves into any of the 10 squares on your opponent’s starting line, he exits the labyrinth. Remove it from the game and place it in front of you to symbolize 1 VP. It is not possible to stay on your opponent’s starting line or to move once on it. On the other hand, your characters can move, rest or initiate Combat on your own starting line. You can exit the labyrinth by moving through an opponent’s wounded character standing on his starting line. You can also initiate Combat against an opponent’s character standing on his starting line, as long as your attacking character is still in a room and still in the labyrinth. If a character leaves the labyrinth while transporting a wounded character, the wounded character is safe (remove from the game) but is not worth any VP. If a character leaves the labyrinth while transporting an object, this object is removed from the game unless it is the Treasure which is worth 1 VP (place the Treasure in front of you to keep track of your extra VP.) == Cards == === Action Cards === The Active Player chooses an Action card from his deck and places it face-up in front of him. All of a player’s Action cards must be stacked together face-up, so that only the last card played is visible. At the end of a turn, if a player has no more Action cards, he gets his 4 Action cards back (see phase 3). This is called a completed Action Card Cycle. During the first turn, the first player can only play a “2 Actions” card. Then, during the entire duration of the first Action Cards Cycle, a player can only play a card whose Actions number is inferior, equal or superior by 1 to the highest Action card played since the beginning of the game. This rule only applies to the first Action Card Cycle. As soon as a “4 Actions” card has been played, any player can play any Action card for the rest of the game. === Combat Cards === You need to spend 1 AP to initiate Combat. A character can attack any adjacent enemy character. You cannot initiate a Combat through a closed Portcullis or a wall. Each player selects a Combat card from his hand and places it face-down in front of him. Both cards are then revealed simultaneously. Each player adds the card’s value to his character’s Combat value (black number on the right on his character token). The player with the highest total wins the Combat and the opponent’s character is wounded. Wounded characters are placed face-down. In the case of a tie, nothing happens and the player whose turn it is can decide to spend 1 new AP to initiate a new Combat. All used Combat cards are removed from the game. Gather them in a single face-down pile. Players are not allowed to look at these cards. The “Combat +0” card is the only card that the owner always gets back. The Active Player cannot attack again a character that has been wounded during this turn, even if another character did the wounding. === Jump Cards === Each player starts the game with 3 “Jump” cards. You can use a Jump card to allow any of your characters to jump over a Pit Trap. Your character can jump over the Pit Trap and land on a square directly behind it (figure 6). A Jump card allows you to move two squares: the first square crossed must be the Pit Trap and the character must then land on a valid square adjacent to the Pit Trap. A valid square is any square where the character can complete his movement while obeying the second Golden Rule. Playing a Jump card costs 1 AP. The used Jump cards are removed from the game after use and placed face-down with the used Combat cards. It is not permitted to jump over a Pit Trap that is occupied by a living or wounded character. 57ee9e6ceeeeba8770e56f1d8cd3393830fbdc82 Tools and tips of BGA Studio 0 99 2024 1926 2016-10-14T12:10:31Z Victoria la 11989 wikitext text/x-wiki == Server Tools and Tips == === Starting a game in one click === To start a game: * Create a new table with your game. * If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table. * Click on "Express Start". === Stopping a game in one click === * Click on the "quit" icon on the top right of the screen. * Click on "Express Stop". === Switching between users === When running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective. === Access to game database and Logs === At the bottom of the game area, there is section without a title containing 3 useful links: Go to game database • BGA request&SQL logs • BGA unexpected exceptions logs * "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game * BGA request&SQL logs - link to your studio PHP log - all tables, all severities. Anything you print using debugging and tracing functions from PHP and some framework logs * BGA unexpected exceptions logs - same log as above but only severity warning and higher See [Practical debugging] for more info about it. === Save & restore state === Using links of this section, you can save the complete current (database) state of your game, then restore it later. This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine. We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations. Limits: * the "restore" function does not work anymore when the game is over. * a saved situation from a given table cannot be restored in another table. * when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually. === Input/Output debugging section === This section shows you: * The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">" * The notifications received by your game interface. Notifications (inputs) begins with "<". Note: if you click on some notification title, you can resend it immediately to the user interface. === Run PHP functions from the chat === On BGA Studio, you can directly run a PHP method from the table chat. For example, if on your PHP you have this method: function giveMoneyToPlayer($player_id, $amount) { ... } You can call this method directly from the chat like this: giveMoneyToPlayer(2564,2) Note: this is not a real php statement, you cannot use self::, you cannot use ";" at the end and you cannot use quotes, if you need to pass a string skip the quotes, like this giveToActivePlayer(money,2) === Stopping Hanging Game === If game is hanging and you cannot enter it to stop you can type this URL (replace 12345 with your table number), which should bring you to a place where you can stop it without entering: <nowiki>http://en.studio.boardgamearena.com/#!table?table=12345</nowiki> == Desktop/Client Tools and Tips == === Eclipse For PHP Developers === Eclipse PHP package can be starting point for development you need. You may also want to install Tern JS plugins to understand dojo style JS. All desktops. https://projects.eclipse.org/projects/tools.pdt === Visual Studio Code === Microsoft Visual Studio Code is light weight IDE/Editor. All desktops. https://code.visualstudio.com === Gedit (Ubuntu) === '''Edit TPL''' To edit TPL with HTML code highlightings in Gedit under Ubuntu: find gtksourceview directory in /usr/share, depending on your version (2.0, 3.0,...). <br> Here it's 3.0, then type in a terminal window: <pre> sudo gedit /usr/share/gtksourceview-3.0/language-specs/html.lang </pre> then find 'globs' section, and change: <pre> <property name="globs">*.html;*.htm;*.tpl</property> </pre> === File Sync on Windows === Install [http://winscp.net/ WinSCP]. Map a remote directory to a local one and enable continuous sync (one way). You need SFTP password you get when you registered dev account. === File Sync on Linux === * Option 1 - Nautilus (file manager) You can just use Nautilus "connect to a server" function with URL sftp://1.studio.boardgamearena.com Then you'll get a mounted local folder mapping your studio folder and you can use any editor you like without further need for sync. Downside - if connection goes down you cannot work on source code, no local copy. * Option 2 - sftp and rsync <pre> #!/bin/bash BASEDIR=`dirname $0` REMOTE=$BASEDIR/remote LOCAL=$BASEDIR/workspace GAME=mygamenamehere #mount remote fusermount -u $REMOTE #this unmounts dir echo LongDevPassword | sshfs -o password_stdin myusernamehere@1.studio.boardgamearena.com: $REMOTE #this starts auto-sync from local to remote mount killall lsyncd lsyncd -deplay 1 -rsync $LOCAL/$GAME/ $REMOTE/$GAME </pre> This can be able run on startup, so you don't have to do anything manually. However sshfs is not very stable you have to kill and restart it sometimes. And remote goes away sometimes due to connection issues with studio. In this case its handy to have a local copy. You can also sync on demand (from a build script or editor command) using rsync -vlrt $LOCAL/$GAME/ $REMOTE/$GAME === Debugging === Browser is the best tool for debugging, see [[Practical debugging]] for details. === Version Control === Studio providers svn for you code on server, however there is no way to access history, restore or do anything with it unless you ask admins. If you want to keep your code in another repository. I suggest to use git with local repo, which you can sync to cloud or backup. === PHP CLI === Its handy to have php cli (command line) tools install to run php locally, so you can test some stuff without deployment cycle. === ImageMagick === Handy set of image manipulation command line tools, useful to for example to stitch together bunch of images and re-size, to use as sprite (in Stock component for example). I.e. you got a graphics file from publisher where every time is 600x600 PNG file with every time in separate file. You want .jpg instead of .png to make it not like 20Mb, all images in one column with size 128x128 /usr/bin/montage `ls Tiles*.png` -tile 1 -geometry 128x128+0+0 ../out/tiles128.jpg 862805620967925960a68abe1530cc32728a5a17 2028 2024 2016-10-14T12:35:00Z Victoria la 11989 wikitext text/x-wiki == Server Tools and Tips == === Starting a game in one click === To start a game: * Create a new table with your game. * If you want to play a game with 3 players, specify that you want a maximum of 3 players at this table. * Click on "Express Start". === Stopping a game in one click === * Click on the "quit" icon on the top right of the screen. * Click on "Express Stop". === Switching between users === When running a game on Studio, you can use the little red arrow near each player's name to open a new tab with this player's perspective. === Access to game database and Logs === At the bottom of the game area, there is section without a title containing 3 useful links: Go to game database • BGA request&SQL logs • BGA unexpected exceptions logs * "Go to game database" link is an immediate access to the PhpMyAdmin tool to view/edit the tables of the current game * BGA request&SQL logs - link to your studio PHP log - all tables, all severities. Anything you print using debugging and tracing functions from PHP and some framework logs * BGA unexpected exceptions logs - same log as above but only severity warning and higher See [Practical debugging] for more info about it. === Save & restore state === Using links of this section, you can save the complete current (database) state of your game, then restore it later. This is particularly useful when you want to develop a part of the game that is difficult to reproduce: you just have to save the situation just before, and then restore it until this part works fine. We provide you 3 "slots": 1, 2 and 3. This way, you can save 3 different game situations. Limits: * the "restore" function does not work anymore when the game is over. * a saved situation from a given table cannot be restored in another table. * when you "restore" a situation, the current browser page is refreshed to reflect the updated game situation, but you have to refresh you other tabs/pages manually. === Input/Output debugging section === This section shows you: * The AJAX calls made by your game interface to the game server. AJAX calls (outputs) begins with ">" * The notifications received by your game interface. Notifications (inputs) begins with "<". Note: if you click on some notification title, you can resend it immediately to the user interface. === Run PHP functions from the chat === On BGA Studio, you can directly run a PHP method from the table chat. For example, if on your PHP you have this method: function giveMoneyToPlayer($player_id, $amount) { ... } You can call this method directly from the chat like this: giveMoneyToPlayer(2564,2) Note: this is not a real php statement, you cannot use self::, you cannot use ";" at the end and you cannot use quotes, if you need to pass a string skip the quotes, like this giveToActivePlayer(money,2) === Stopping Hanging Game === If game is hanging and you cannot enter it to stop you can type this URL (replace 12345 with your table number), which should bring you to a place where you can stop it without entering: <nowiki>http://en.studio.boardgamearena.com/#!table?table=12345</nowiki> == Desktop Tools == === Eclipse For PHP Developers === Eclipse PHP package can be starting point for development you need. You may also want to install Tern JS plugins to understand dojo style JS. All desktops. https://projects.eclipse.org/projects/tools.pdt === Visual Studio Code === Microsoft Visual Studio Code is light weight IDE/Editor. All desktops. https://code.visualstudio.com === Gedit (Ubuntu) === '''Edit TPL''' To edit TPL with HTML code highlightings in Gedit under Ubuntu: find gtksourceview directory in /usr/share, depending on your version (2.0, 3.0,...). <br> Here it's 3.0, then type in a terminal window: <pre> sudo gedit /usr/share/gtksourceview-3.0/language-specs/html.lang </pre> then find 'globs' section, and change: <pre> <property name="globs">*.html;*.htm;*.tpl</property> </pre> === File Sync on Windows === Install [http://winscp.net/ WinSCP]. Map a remote directory to a local one and enable continuous sync (one way). You need SFTP password you get when you registered dev account. === File Sync on Linux === * Option 1 - Nautilus (file manager) You can just use Nautilus "connect to a server" function with URL sftp://1.studio.boardgamearena.com Then you'll get a mounted local folder mapping your studio folder and you can use any editor you like without further need for sync. Downside - if connection goes down you cannot work on source code, no local copy. * Option 2 - sftp and rsync <pre> #!/bin/bash BASEDIR=`dirname $0` REMOTE=$BASEDIR/remote LOCAL=$BASEDIR/workspace GAME=mygamenamehere #mount remote fusermount -u $REMOTE #this unmounts dir echo LongDevPassword | sshfs -o password_stdin myusernamehere@1.studio.boardgamearena.com: $REMOTE #this starts auto-sync from local to remote mount killall lsyncd lsyncd -deplay 1 -rsync $LOCAL/$GAME/ $REMOTE/$GAME </pre> This can be able run on startup, so you don't have to do anything manually. However sshfs is not very stable you have to kill and restart it sometimes. And remote goes away sometimes due to connection issues with studio. In this case its handy to have a local copy. You can also sync on demand (from a build script or editor command) using rsync -vlrt $LOCAL/$GAME/ $REMOTE/$GAME === Debugging === Browser is the best tool for debugging, see [[Practical debugging]] for details. === Version Control === Studio providers svn for you code on server, however there is no way to access history, restore or do anything with it unless you ask admins. If you want to keep your code in another repository. I suggest to use git with local repo, which you can sync to cloud or backup. === PHP CLI === Its handy to have php cli (command line) tools install to run php locally, so you can test some stuff without deployment cycle. === ImageMagick === Handy set of image manipulation command line tools, useful to for example to stitch together bunch of images and re-size, to use as sprite (in Stock component for example). I.e. you got a graphics file from publisher where every time is 600x600 PNG file with every time in separate file. You want .jpg instead of .png to make it not like 20Mb, all images in one column with size 128x128 /usr/bin/montage `ls Tiles*.png` -tile 1 -geometry 128x128+0+0 ../out/tiles128.jpg == Client Tips == === Speed up game re-loading by disabling Input/Output debug section === Development UI have few sections for debugging only, such as 'Input/Output debugging section'. Loading this data will significantly slow down your reload. I did some profiling and my reloading (i.e. F5) took 14 seconds, 12 of which it was dealing with loading this section. If you not using it you can disable it. In your JavaScript code, in the begging of 'setup' method add this code dojo.destroy('debug_output'); That should get rid of this section and overhead associated with loading it (it may have some other side-effects, I have not explored all of them) b47b7a0a9a561fafa27ddf5e0f08cf9a7c642261 Studio logs 0 127 2025 899 2016-10-14T12:15:46Z Victoria la 11989 /* BGA unexpected exceptions logs */ wikitext text/x-wiki BGA Studio logs are available directly from your game development interface. Logs allows you to check out what happened recently on server and to debug your game. == BGA request&SQL logs == This log is useful: * When you want to check what SQL requests has been built during a request. * When you want to debug your PHP code using "self::trace" * When you want to know why a request takes too many time. On this log, you can see: === Your requests === Example: 20/06 21:50:56 [info] [T403] [4/mytest0] /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 Note that the best way to check your Ajax request is to read the [[http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#Input.2FOutput_debugging_section Input/Output section]]. === Request responses === Example: 20/06 21:50:56 [notice] [T403] [4/mytest0] OK-0 169 d141 c8 e0 I9 A158 V0 T0 /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 You can recognize a response because it contains [notice]. Usually, there is one response for each request. Let's details the beginning of the log: * 20/06 21:50:56: the date * [notice] * [T403]: this is a log from table 403 * [4/mytest0]: this is use "mytest0", with id 4 * OK-0: it means that the request ended up successfully, with no exception (expected or unexpected). * 169: this is the time taken to process the request (169ms). * d141: this is the total Database time used to process the request (141ms). === SQL requests === Example: 20/06 21:50:56 [info] [T403] [4/mytest0] 0.26 SELECT player_tokenColor FROM player WHERE player_id ='4' All requests to Database are traced in this log. You can see here the time take by the request (0,26ms). === Custom trace === You can use special PHP methods in your PHP code to left some trace in this log: * self::trace( "your message here" ); // Display "your message here" in the log * self::dump( "My variable", $variable_to_dump ); // Display the content of $variable_to_dump in the log == BGA unexpected exceptions logs == In this log you can check the last Unexpected exceptions from your game. Exceptions management on PHP side [[http://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Managing_errors_and_exceptions is described here]]. The log displayed the complete stacktrace of the exception, so you can debug it. The SQL log is very verbose and sometimes it too hard to extract your tracing from it, in this case you can use error log for tracing temporarily. You can add debug statement using self::warn() which will appear in that the log. Do not leave these tracing method calls after you done debugging unless they are real warnings or errors. ad1b0bb65b46bf83c06f5a7f75be3810689d1677 2027 2025 2016-10-14T12:28:13Z Victoria la 11989 /* BGA unexpected exceptions logs */ wikitext text/x-wiki BGA Studio logs are available directly from your game development interface. Logs allows you to check out what happened recently on server and to debug your game. == BGA request&SQL logs == This log is useful: * When you want to check what SQL requests has been built during a request. * When you want to debug your PHP code using "self::trace" * When you want to know why a request takes too many time. On this log, you can see: === Your requests === Example: 20/06 21:50:56 [info] [T403] [4/mytest0] /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 Note that the best way to check your Ajax request is to read the [[http://en.doc.boardgamearena.com/Tools_and_tips_of_BGA_Studio#Input.2FOutput_debugging_section Input/Output section]]. === Request responses === Example: 20/06 21:50:56 [notice] [T403] [4/mytest0] OK-0 169 d141 c8 e0 I9 A158 V0 T0 /cinco/cinco/exchange4Cards.html?id=4&lock=97d1c7a1-903a-4d1f-8206-de39ce8204fc&table=403&testuser=4&dojo.preventCache=1371757856044 You can recognize a response because it contains [notice]. Usually, there is one response for each request. Let's details the beginning of the log: * 20/06 21:50:56: the date * [notice] * [T403]: this is a log from table 403 * [4/mytest0]: this is use "mytest0", with id 4 * OK-0: it means that the request ended up successfully, with no exception (expected or unexpected). * 169: this is the time taken to process the request (169ms). * d141: this is the total Database time used to process the request (141ms). === SQL requests === Example: 20/06 21:50:56 [info] [T403] [4/mytest0] 0.26 SELECT player_tokenColor FROM player WHERE player_id ='4' All requests to Database are traced in this log. You can see here the time take by the request (0,26ms). === Custom trace === You can use special PHP methods in your PHP code to left some trace in this log: * self::trace( "your message here" ); // Display "your message here" in the log * self::dump( "My variable", $variable_to_dump ); // Display the content of $variable_to_dump in the log == BGA unexpected exceptions logs == In this log you can check the last Unexpected exceptions from your game. Exceptions management on PHP side [[http://en.doc.boardgamearena.com/Main_game_logic:_yourgamename.game.php#Managing_errors_and_exceptions is described here]]. The log displayed the complete stacktrace of the exception, so you can debug it. The SQL log is very verbose and sometimes it too hard to extract your tracing from it, in this case you can use error log for tracing temporarily. You can add debug statement using self::warn() which will appear in that the log. Do not leave these tracing method calls after you done debugging unless they are real warnings or errors (only the error log level will appear in production). 2453d3682c99d8f8fb79613f8ec688de277b3610 Practical debugging 0 100 2026 1923 2016-10-14T12:26:51Z Victoria la 11989 /* Add traces to your code */ wikitext text/x-wiki This page gives you practical tips to debug your game during the development. Don't hesitate to share with us your difficulties in order we can improve this section. == Tools == To work on BGA Studio, we recommend you to use [www.google.com/chrome Google Chrome] as it's the current fastest browser for BGA platform, and it's available in all OS. Another reason to use Chrome is that it embed all tools you need to work on BGA Studio. You can see them by pressing "F12" or from the menu ("Tools > Development tools"). A good practice is to use a second browser to develop the game, in order to check that your game is working fine on this browser too. To debug with Firefox browser, we advise you to use these 2 extensions: * [https://addons.mozilla.org/firefox/addon/firebug/ Firebug] * [https://addons.mozilla.org/firefox/addon/web-developer/ Web developper] To debug with Internet Explorer, we advise you to use one of the most recent version (ex: IE9). Last versions of Internet Explorer have way better development tools than the previous ones... == General tip for debugging == In general for debugging, think of using the '[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]] state' functionality. It enables you to save the state of your game just before the issue you are investigating, then come back to that point with one click as many times as needed to understand what is going wrong. You can save up to 3 different states. == Debugging my game when it cannot start == If your game don't start because of an error, you are probably in one of these situations: * There is a SQL error in your dbmodel.sql file. * You have a syntax error in your PHP file. * Your PHP "setup" - or any method used during the game initial states - generates an exception. If the error is not explicitly displayed when you click on "Express start", you should check the "Gameserver error log" as per [[Studio logs]]. == Debugging my PHP game logic (or my view) == Most of the time, debugging PHP is quite easy. Here's what I do when I want to develop/debug some game logic that is triggered by some game action: * At first, I make sure that I can reproduce the needed game situation in one click. To do this, I use the "[[Tools_and_tips_of_BGA_Studio#Save_.26_restore_state|save & restore]]" function. * Another possibility for this is to place a '''die('ok');''' PHP statement right after the PHP I am developing/debugging. This way, I make sure that every request will fail and then nothing will be commited to the database, anyway. * Then, I use '''var_dump''' function to dump PHP variables and check what's wrong, until it works. Example: <pre> // (...my code to debug) var_dump( $my_variable ); die('ok'); // (...my code to debug) </pre> === Add traces to your code === You can use the following functions in your game to add server side logging: '''self::debug( $message );''' // debug level logging, goes to [[Studio_logs|BGA request&SQL logs]] '''self::trace( $message );''' // info level logging, goes to [[Studio_logs|BGA request&SQL logs]] '''self::warn( $message );''' // warning level logging, goes to [[Studio_logs#BGA_unexpected_exceptions_logs|BGA unexpected exceptions log]] '''self::error( $message );''' // error level logging, goes to [[Studio_logs#BGA_unexpected_exceptions_logs|BGA unexpected exceptions log]] Check [[Studio logs]] for more details on how to access your logs. This can be useful when you need to follow the flow of your code and not just stop it to see how it goes at some point. Only the error log level will appear in production. This level should be used only for critical problems. Other levels will show only in the development environment and can be used as you see fit. == Debugging my HTML/CSS layout == Situation examples: * why my game element doesn't show up in the interface? * why my CSS property hasn't been applied to this element? * why this game element is displayed at this position? A first useful tip when an element does not show up in the interface is to give it a red background: <pre> #my_element { ... some CSS definitions ... background-color: red; } </pre> This way, you know if the element is not visible because of some of its CSS property or because of anything else. Another tip: sometimes, you change a CSS property with no visible effect on your interface. In that case, add a "display:none" property. If your element does not disappear, the bug probably comes from your CSS selector and not from your CSS property. Using Chrome "Elements" tab (thre first one), you can: * See the CURRENT HTML of your page. Remember that the classical "show page source" is inefficient with BGA as you are modifying the page source with your Javascript code. * Using the "magnifying glass", you can click on any part of your game interface and check it's HTML code and associated CSS styles. * You can even modify directly some CSS property and see if how it looks immediately on the game interface. == Debugging my Javascript game interface logic == Compare to PHP debugging, Javascript debugging can sometimes be painful. Here's are some tips to make your life easier while developing and debugging Javascript: === Do complex things on PHP side === PHP side is more reliable and simpler to debug than Javascript. Then, when you need to perform a complex operation, check first it you can't write it on server side first. The most frequent case is the following: you want to compute possible moves in a game situation. Doing it in Javascript is a nightmare. Then, do it on PHP, and transfer the result to your client interface using the "args" game state property. Note: check Reversi example for this. === Add traces in your code === You can use the following: '''console.log( variable_to_inspect )''' It will give you the object structure of the variable in the Javascript console, without blocking the execution. It's often a good idea to precede this call with a console.log( '### HERE ###' ); to find more easily the appropriate line in the console log. '''alert( variable_to_inspect )''' It will popup what you wish and pause the execution until you click ok. This won't be useful for complex structures, only native types will get plainly displayed. But this is sometimes useful just with messages to make sure which way the execution goes. == Some frequent errors == See [[Troubleshooting]]. 7b8fb87507286e159dde9b1ee63629980df48b22 Gamehelptokaido 0 134 2029 1861 2016-10-16T10:53:02Z Ken258 14615 /*  Objective of the game */ wikitext text/x-wiki ==  Objective of the game == The players are travelers in Japan. They follow the prestigious Tokaido and try to make this journey as rich an experience as possible. They will pass through magnificent countryside, taste delicious culinary specialties, purchase souvenirs, benefit from the virtues of hot springs, and have unforgettable encounters. GAMEPLAY:https://www.youtube.com/watch?v=HD0J7Ejr7qc ==Playing the game== The player whose Traveler is farthest behind on the road is the player who takes the next turn. This player must move his Traveler forward to the open space (dot) of his choice, freely passing over one or more open spaces. Once he has moved his Traveler, the player receives the benefit corresponding to this type of space. '''NOTE:''' Some of the spaces on the board are doubled. Double spaces are used only in games with 4 or 5 players. ==Description of the spaces== ''(Standard Option for '''B'''ase Game / Additional Option for '''E'''xpansion Game)'' ===Encounters=== :('''B''') The player draws one Encounter card and receives a bonus: ::* Annaibito - Draw the indicated panoramas, if completed draw a panoramas of your choice. ::* Kuge - Gain 3 coins. ::* Miko - Add 1 point and 1 coin to the Temple (from the bank) ::* Samurai - Gain 3 points. ::* Shokunin - Draw a Souvenir card and score those points. :: ''New Encounters Promo Cards'' ::* ''Itamae - Pay a coin to draw a meal card add it if you don't own it and score 6 points.'' ::* ''Kitoushi - Pay a coin to chose a Panoramas and score the corresponding points.'' ::* ''Saru - Draw a Hot Spring card and score those points.'' ::* ''Takuhatsuso - Pay a coin and score 4 points.'' :('''E''') Pay 1 coin and draw a Calligraphy card (counts for ''Chatterbox'' accomplishment) and gains end game bonuses: ::* Contemplation - 3 points for each completed Panorama and 1 point per Cherry Tree. ::* Fasting - Score 3 points for each uneaten meal at the Inn. ::* Foresight - 2 points per coin. ::* Nostalgia - 2 points for each Legendary Object and 1 point per Souvenir. ::* Patience - Score 6 points if you are the last to arrive in the last in, otherwise score 2 points. ::* Perfection - 2 points for each Accomplishment and 1 point for each Calligraphy card. ===Farm=== :('''B''') The player earns 3 coins. :('''E''') Player gambles 2 coins; (X= Loses coins, 1= Recovers coins, 2/3/3/4= Gains double that many coins). ===Hot Springs=== :('''B''') The player takes a Hot Spring card. These cards are worth 2 or 3 points. :('''E''') Pay 1 coin for a Bath House card worth 4 points (counts for ''Bather'' accomplishment). ===Panorama=== :('''B''') There are three Panorama types and are made of 3 (Field), 4 (Mountain), or 5 (Paddy) sections. : When a player stops on a Panorama they take the first Panorama of that type that they do not have (value from 1-5) and scores that many points. Each traveler can create only a single panorama of each type and when completed can no longer stop on the spaces corresponding to that type. :('''E''') A player may instead take a Cherry Tree and gain 2 points and 1 coin. (''There are 6 Cherry Tree cards.'') ===Temple=== :('''B''') The player must donate 1, 2, or 3 coins to the temple and scores 1 point for each donated coin. :('''E''') Pay 1 coin to take one of the available Amulet cards. ::* Vitality - Take another turn when in the lead. ::* Fortune - Roll the fortune die and gain 0-4 coins. ::* Health - Take both options at your location. ::* Friendship - Share a single space occupied by another traveler. ::* Hospitality - When stoppping at the Inn pay 0 coins for a card. ::* Devotion - When buying something, donate the coins spent to the Temple and earn points. ===Village=== :('''B''') The player draws 3 Souvenir cards and can purchase 1-3 of these cards for 1-3 coins. There are four different Souvenirs and are grouped in sets. The first Souvenir in each set is worth 1 point, the next is 3 points, then 5 and 7 points. :('''E''') Acquire a Legendary Object (counts for ''Collector'' accomplishment) for 1-3 coins: :* Shodo & Emaki - For 1 coin, gain 1 point for each Souvenir or Legendary Object. Gain 1 point for each Souvenir thereafter. :* Buppatsu & Ema - For 2 coins this counts as a different Souvenir type, 5 types in a set is worth 9 points. :* Murasame & Masamune - For 3 coins, gain 8 points. ===Inns=== : All Travelers must stop at each Inn, they may not leave until all players have arrived at that Inn. : The Inns allow players to buy one unique Meal card for 1-3 coins that are worth 6 points. : When the first traveler arrives at an Inn, they draw as many Meal cards as there are players, plus 1. : As players arrive at the Inn they may buy a Meal card to add to their collection, hidden from other players. :* ''A traveler cannot taste the same culinary specialty twice during their journey.'' :* ''A traveler can never purchase more than one Meal card per Inn.'' :* ''A traveler is never obliged to purchase a Meal card.'' == End of the journey == When all of the Travelers have arrived in Edo at the last Inn, the game ends. The travelers score additional points depending on their ranking as donors to the Temple: * The most generous donor scores 10 points. * The second scores 7 points. * The third scores 4 points. * All other donors score 2 points. Award the following achievement cards to the appropriate travelers. Each achievement card is worth 3 points. If players are tied for an achievement, then they each receive the 3 points. * Gourmet - the player with the highest total face value of Meal cards. * Collector - the player with the most Souvenir cards. * Bather - the player with the most Hot Spring cards. * Chatterbox - the player with the most Encounter cards. Note: There are 3 other achievement cards that are awarded during game play. One for each different type of panorama and each is awarded to the player that is first to complete the specific panorama. Note: If players are tied after the final scoring, then the player with the most achievement cards wins. == Description of the Travelers == '' '''Name''' (starting coins) Special powers'' === Base Game=== * '''Chuubei''' (4) At intermediate inns, before meal, draws encounter card * '''Kinko''' (7) At inns, buys meals at 1 coin discount * '''Hiroshige''' (3) At intermediate inns, before meal, acquires panorama card of choice * '''Hirotada''' (8) At temple spaces, may take 1 coin from the bank and donate it to the temple, scoring 1 point; does this in addition to normal temple action * ''''Mitsukuni''' (6) Earns 1 additional point per hot spring and achievement card * '''Sasayakko''' (5) At village spaces, when purchasing at least two souvenirs, the cheapest is free; must have enough coins to pay for both at full price * '''Satsuki''' (2) At inns, selects one meal card at random from the set of meal cards; may take it for free or purchase another at full price * '''Umegae''' (5) At encounter spaces, gains 1 coin and 1 point before drawing encounter card * '''Yoshiyasu''' (9) At encounter spaces, draws two encounter cards and keeps one; places other on bottom of deck * '''Zen-emon''' (6) At village spaces, may purchase one souvenir for 1 coin instead of full price ===Crossroads=== * '''Daigoro''' (3) At intermediate inns, before meal, draws souvenir card * '''Gotozaemon''' (0) At panorama spaces, gains 1 additional coin * '''Jirocho''' (5) At intermediate inns, before meal, may gamble 1 coin; player throws the fortune die and follows normal rules for gambling * '''Kita''' (4) At encounter spaces, may take both actions (draw encounter card '''and''' buy calligraphy card) * '''Miyataka''' (4) At temple spaces, may take both actions (donate coins '''and''' buy amulet) * '''Nampo''' (2) At inns, earns 1 point per coin value of meal eaten == Game Options == === Initiation === A simplified version with no Travelers and everyone starting with 7 coins. === Return Trip === Instead of starting on the left side of the board, players move right to left. === Gastronomy === The first person arriving at an Inn draws one less card, only drawing one card per player. === Preparations === When leaving the starting Inn, the last player gains two coins, the next gains one coin, the fourth and fifth players each lose a coin. === Crossroads === This expansion adds a second option at each location (other than the Inns) to choose from when stopping. === New Encounters === This adds 4 new encounters to the possibilities when on the 'Encounters' space. 50fa3c33fb42ba10e68bae71dce40ab1851a207e Gamehelpdragonline 0 236 2030 2016-10-17T12:37:51Z Cb droege 8532 Initial post. Copied with permission from in-game summary card wikitext text/x-wiki == Play Summary == '''Draft Phase'''<br> Shuffle Deck.<br> Deal 15 cards to each player, discarding remainder.<br> Draft one card and trade decks.<br> Draft two cards and trade decks.<br> Draft three cards and trade decks.<br> Set aside drafted cards.<br> '''Line-up Phase'''<br> Choose four cards, discarding the remaining five.<br> Place cards face-down toward opponent.<br> '''Battle Phase'''<br> Place activation tokens face-down next to starting line cards.<br> When both players are ready, reveal all cards and tokens.<br> Calculate battle results.<br> Remove destroyed Dragons.<br> Fill lines at back from players’ hands.<br> Replay battle phase until one player cannot fill their line.<br> 928d1918deb5f5cdc2dffe64c542b4b9c7174940 Gamehelplostcities 0 210 2031 1767 2016-10-17T19:46:04Z Zahlman 543 copyediting and spacing; also clarified that 20 is not subtracted for unstarted expeditions wikitext text/x-wiki '''THE DECK:''' 5 suits (corresponding to the "expeditions" on the play field) of 9 cards each (numbered 2-10), plus 3 "investment" or "handshake" cards. '''PLAY:''' On your turn, you must: 1. Either add one card to an expedition (suit) or discard one to the appropriate pile on the board. 2. Pick up the top card from the stock pile or from one discard pile. Both actions are mandatory. Cards must be added in ascending sequence, but gaps are permitted. Investment cards may precede a numerical card, but may not be added afterward. Players need not embark on all 5 expeditions; only those that are embarked on by a player count toward that player's score. The game ends immediately when the last card is picked up from the stock pile. '''SCORING:''' Your score is the sum of the points you scored for each of the five expeditions, counted as follows: 1. Take the sum of all numbered cards in the expedition 2. Subtract 20 if you played any cards to it (including investment cards) 3. Multiply by (number of investment cards + 1) 4. Add 20 if the expedition contains 8 or more cards e3bf90243cef4f3f4408d80b8b24eebb56150611 Gamehelpakeruption 0 237 2032 2016-10-21T16:51:30Z Stratusgames 14668 First draft of rules summary wikitext text/x-wiki == Introduction == The inhabitants of the villages surrounding a dormant volcano were happily living in peace until — KABOOM! — the old volcano sprung back to life, unleashing rivers of molten lava in every direction and blasting volcanic rock into the sky. The villages, now faced with destruction, must do whatever they can to protect their homes from the incoming surge of lava. Your village is about to burn up — can you take the heat? == Overview == Players control villages that are threatened by an erupting volcano. Protect your village by placing lava tiles and building walls strategically, while also trying to direct lava toward the other villages to gain valuable action cards. The player whose village is at the lowest temperature at the end of the game, wins. == Turns == Do the following on each turn, in order: '''1) Assess damage''' - your village heats up 20 degrees on the Burn Meter for each lava flow entering your village that is not blocked by a wall. For each lava flow that is blocked by a wall, roll the dice; if the lava (orange) wins the roll, your village heats up 10 degrees and the wall is discarded. If the wall is wood, add 1 point to the white die; if the wall is stone, add 2 points to the white die. Lava (orange) wins ties. '''2) Draw and place a lava tile''' - place the tile so that all lava flows and grassy areas connect properly to other tiles. If you place a tile on a resource space, you gain a wall of that material. If you place a tile next to any village on the board, you draw an action card for each lava flow touching the village. If you want to place a tile next to a lava flow that is blocked with a wall, you must roll the dice and the lava must win the dice roll (or else you have to place the tile elsewhere). '''3) Play as many action cards as desired''' - you can only keep a maximum of 3 Action Cards at the end of your turn. To play a card, discard it and either carry out the effect shown on the card or retrieve a wall of the material shown (you cannot do both). You can also optionally discard 2 cards to gain an additional tile placement. '''4) Build a wall (optional)''' - place a wall piece (of any material) on the border next to your village or on a specific lava flow on the board. == Burn Meter == As a village heats up on the Burn Meter, the player who owns the village gains additional abilities in each Danger Zone. '''Danger Zone 1''' - the player may build an extra wall on his turn. '''Danger Zone 2''' - the player may draw an Action Card AND build an extra wall on his turn. '''Danger Zone 3''' - the player may place an extra Lava Tile AND draw an Action Card AND build an extra wall on his turn. The first player to enter each Danger Zone must place the corresponding Eruption tile. This tile can be placed anywhere on the board and does not have to connect to other tiles (it is its own source of lava). When this tile is placed, all other players increase in temperature by 30 degrees. == Ending the Game == The game ends when either of the following events occurs: ''' 1) A village reaches the last space on the Burn Meter and remains there at the end of the turn.''' The remaining Lava tiles are removed from the board and the other players take one final turn. '''2) The last Lava Tile is placed.''' The current player finishes his turn, and all players (including the current player) take one final turn. The player with the lowest temperature on the Burn Meter wins! c8402e4b8a399b9aae87ba7eb3ab1a71e973e625 2033 2032 2016-10-21T16:52:48Z Stratusgames 14668 /* Introduction */ wikitext text/x-wiki The inhabitants of the villages surrounding a dormant volcano were happily living in peace until — KABOOM! — the old volcano sprung back to life, unleashing rivers of molten lava in every direction and blasting volcanic rock into the sky. The villages, now faced with destruction, must do whatever they can to protect their homes from the incoming surge of lava. Your village is about to burn up — can you take the heat? == Overview == Players control villages that are threatened by an erupting volcano. Protect your village by placing lava tiles and building walls strategically, while also trying to direct lava toward the other villages to gain valuable action cards. The player whose village is at the lowest temperature at the end of the game, wins. == Turns == Do the following on each turn, in order: '''1) Assess damage''' - your village heats up 20 degrees on the Burn Meter for each lava flow entering your village that is not blocked by a wall. For each lava flow that is blocked by a wall, roll the dice; if the lava (orange) wins the roll, your village heats up 10 degrees and the wall is discarded. If the wall is wood, add 1 point to the white die; if the wall is stone, add 2 points to the white die. Lava (orange) wins ties. '''2) Draw and place a lava tile''' - place the tile so that all lava flows and grassy areas connect properly to other tiles. If you place a tile on a resource space, you gain a wall of that material. If you place a tile next to any village on the board, you draw an action card for each lava flow touching the village. If you want to place a tile next to a lava flow that is blocked with a wall, you must roll the dice and the lava must win the dice roll (or else you have to place the tile elsewhere). '''3) Play as many action cards as desired''' - you can only keep a maximum of 3 Action Cards at the end of your turn. To play a card, discard it and either carry out the effect shown on the card or retrieve a wall of the material shown (you cannot do both). You can also optionally discard 2 cards to gain an additional tile placement. '''4) Build a wall (optional)''' - place a wall piece (of any material) on the border next to your village or on a specific lava flow on the board. == Burn Meter == As a village heats up on the Burn Meter, the player who owns the village gains additional abilities in each Danger Zone. '''Danger Zone 1''' - the player may build an extra wall on his turn. '''Danger Zone 2''' - the player may draw an Action Card AND build an extra wall on his turn. '''Danger Zone 3''' - the player may place an extra Lava Tile AND draw an Action Card AND build an extra wall on his turn. The first player to enter each Danger Zone must place the corresponding Eruption tile. This tile can be placed anywhere on the board and does not have to connect to other tiles (it is its own source of lava). When this tile is placed, all other players increase in temperature by 30 degrees. == Ending the Game == The game ends when either of the following events occurs: ''' 1) A village reaches the last space on the Burn Meter and remains there at the end of the turn.''' The remaining Lava tiles are removed from the board and the other players take one final turn. '''2) The last Lava Tile is placed.''' The current player finishes his turn, and all players (including the current player) take one final turn. The player with the lowest temperature on the Burn Meter wins! 8c3377f3e8efdda3ede04ad5f219719afac7a09b 2034 2033 2016-10-21T16:53:04Z Stratusgames 14668 /* Burn Meter */ wikitext text/x-wiki The inhabitants of the villages surrounding a dormant volcano were happily living in peace until — KABOOM! — the old volcano sprung back to life, unleashing rivers of molten lava in every direction and blasting volcanic rock into the sky. The villages, now faced with destruction, must do whatever they can to protect their homes from the incoming surge of lava. Your village is about to burn up — can you take the heat? == Overview == Players control villages that are threatened by an erupting volcano. Protect your village by placing lava tiles and building walls strategically, while also trying to direct lava toward the other villages to gain valuable action cards. The player whose village is at the lowest temperature at the end of the game, wins. == Turns == Do the following on each turn, in order: '''1) Assess damage''' - your village heats up 20 degrees on the Burn Meter for each lava flow entering your village that is not blocked by a wall. For each lava flow that is blocked by a wall, roll the dice; if the lava (orange) wins the roll, your village heats up 10 degrees and the wall is discarded. If the wall is wood, add 1 point to the white die; if the wall is stone, add 2 points to the white die. Lava (orange) wins ties. '''2) Draw and place a lava tile''' - place the tile so that all lava flows and grassy areas connect properly to other tiles. If you place a tile on a resource space, you gain a wall of that material. If you place a tile next to any village on the board, you draw an action card for each lava flow touching the village. If you want to place a tile next to a lava flow that is blocked with a wall, you must roll the dice and the lava must win the dice roll (or else you have to place the tile elsewhere). '''3) Play as many action cards as desired''' - you can only keep a maximum of 3 Action Cards at the end of your turn. To play a card, discard it and either carry out the effect shown on the card or retrieve a wall of the material shown (you cannot do both). You can also optionally discard 2 cards to gain an additional tile placement. '''4) Build a wall (optional)''' - place a wall piece (of any material) on the border next to your village or on a specific lava flow on the board. == Burn Meter == As a village heats up on the Burn Meter, the player who owns the village gains additional abilities in each Danger Zone. '''Danger Zone 1''' - the player may build an extra wall on his turn. '''Danger Zone 2''' - the player may draw an Action Card AND build an extra wall on his turn. '''Danger Zone 3''' - the player may place an extra Lava Tile AND draw an Action Card AND build an extra wall on his turn. The first player to enter each Danger Zone must place the corresponding Eruption tile. This tile can be placed anywhere on the board and does not have to connect to other tiles (it is its own source of lava). When this tile is placed, all other players increase in temperature by 30 degrees. == Ending the Game == The game ends when either of the following events occurs: ''' 1) A village reaches the last space on the Burn Meter and remains there at the end of the turn.''' The remaining Lava tiles are removed from the board and the other players take one final turn. '''2) The last Lava Tile is placed.''' The current player finishes his turn, and all players (including the current player) take one final turn. The player with the lowest temperature on the Burn Meter wins! e09fbf6ecbaca83ab2ef2de0a7884af2a9620d3e 2035 2034 2016-10-21T16:53:24Z Stratusgames 14668 /* Ending the Game */ wikitext text/x-wiki The inhabitants of the villages surrounding a dormant volcano were happily living in peace until — KABOOM! — the old volcano sprung back to life, unleashing rivers of molten lava in every direction and blasting volcanic rock into the sky. The villages, now faced with destruction, must do whatever they can to protect their homes from the incoming surge of lava. Your village is about to burn up — can you take the heat? == Overview == Players control villages that are threatened by an erupting volcano. Protect your village by placing lava tiles and building walls strategically, while also trying to direct lava toward the other villages to gain valuable action cards. The player whose village is at the lowest temperature at the end of the game, wins. == Turns == Do the following on each turn, in order: '''1) Assess damage''' - your village heats up 20 degrees on the Burn Meter for each lava flow entering your village that is not blocked by a wall. For each lava flow that is blocked by a wall, roll the dice; if the lava (orange) wins the roll, your village heats up 10 degrees and the wall is discarded. If the wall is wood, add 1 point to the white die; if the wall is stone, add 2 points to the white die. Lava (orange) wins ties. '''2) Draw and place a lava tile''' - place the tile so that all lava flows and grassy areas connect properly to other tiles. If you place a tile on a resource space, you gain a wall of that material. If you place a tile next to any village on the board, you draw an action card for each lava flow touching the village. If you want to place a tile next to a lava flow that is blocked with a wall, you must roll the dice and the lava must win the dice roll (or else you have to place the tile elsewhere). '''3) Play as many action cards as desired''' - you can only keep a maximum of 3 Action Cards at the end of your turn. To play a card, discard it and either carry out the effect shown on the card or retrieve a wall of the material shown (you cannot do both). You can also optionally discard 2 cards to gain an additional tile placement. '''4) Build a wall (optional)''' - place a wall piece (of any material) on the border next to your village or on a specific lava flow on the board. == Burn Meter == As a village heats up on the Burn Meter, the player who owns the village gains additional abilities in each Danger Zone. '''Danger Zone 1''' - the player may build an extra wall on his turn. '''Danger Zone 2''' - the player may draw an Action Card AND build an extra wall on his turn. '''Danger Zone 3''' - the player may place an extra Lava Tile AND draw an Action Card AND build an extra wall on his turn. The first player to enter each Danger Zone must place the corresponding Eruption tile. This tile can be placed anywhere on the board and does not have to connect to other tiles (it is its own source of lava). When this tile is placed, all other players increase in temperature by 30 degrees. == Ending the Game == The game ends when either of the following events occurs: '''1) A village reaches the last space on the Burn Meter and remains there at the end of the turn.''' The remaining Lava tiles are removed from the board and the other players take one final turn. '''2) The last Lava Tile is placed.''' The current player finishes his turn, and all players (including the current player) take one final turn. The player with the lowest temperature on the Burn Meter wins! 5bd837975016f4c19758061ff50c5d60aca99a08 2048 2035 2016-11-12T09:54:12Z Hey teacher 6378 /* Ending the Game */ rules if two players tie wikitext text/x-wiki The inhabitants of the villages surrounding a dormant volcano were happily living in peace until — KABOOM! — the old volcano sprung back to life, unleashing rivers of molten lava in every direction and blasting volcanic rock into the sky. The villages, now faced with destruction, must do whatever they can to protect their homes from the incoming surge of lava. Your village is about to burn up — can you take the heat? == Overview == Players control villages that are threatened by an erupting volcano. Protect your village by placing lava tiles and building walls strategically, while also trying to direct lava toward the other villages to gain valuable action cards. The player whose village is at the lowest temperature at the end of the game, wins. == Turns == Do the following on each turn, in order: '''1) Assess damage''' - your village heats up 20 degrees on the Burn Meter for each lava flow entering your village that is not blocked by a wall. For each lava flow that is blocked by a wall, roll the dice; if the lava (orange) wins the roll, your village heats up 10 degrees and the wall is discarded. If the wall is wood, add 1 point to the white die; if the wall is stone, add 2 points to the white die. Lava (orange) wins ties. '''2) Draw and place a lava tile''' - place the tile so that all lava flows and grassy areas connect properly to other tiles. If you place a tile on a resource space, you gain a wall of that material. If you place a tile next to any village on the board, you draw an action card for each lava flow touching the village. If you want to place a tile next to a lava flow that is blocked with a wall, you must roll the dice and the lava must win the dice roll (or else you have to place the tile elsewhere). '''3) Play as many action cards as desired''' - you can only keep a maximum of 3 Action Cards at the end of your turn. To play a card, discard it and either carry out the effect shown on the card or retrieve a wall of the material shown (you cannot do both). You can also optionally discard 2 cards to gain an additional tile placement. '''4) Build a wall (optional)''' - place a wall piece (of any material) on the border next to your village or on a specific lava flow on the board. == Burn Meter == As a village heats up on the Burn Meter, the player who owns the village gains additional abilities in each Danger Zone. '''Danger Zone 1''' - the player may build an extra wall on his turn. '''Danger Zone 2''' - the player may draw an Action Card AND build an extra wall on his turn. '''Danger Zone 3''' - the player may place an extra Lava Tile AND draw an Action Card AND build an extra wall on his turn. The first player to enter each Danger Zone must place the corresponding Eruption tile. This tile can be placed anywhere on the board and does not have to connect to other tiles (it is its own source of lava). When this tile is placed, all other players increase in temperature by 30 degrees. == Ending the Game == The game ends when either of the following events occurs: '''1) A village reaches the last space on the Burn Meter and remains there at the end of the turn.''' The remaining Lava tiles are removed from the board and the other players take one final turn. '''2) The last Lava Tile is placed.''' The current player finishes his turn, and all players (including the current player) take one final turn. The player with the lowest temperature on the Burn Meter wins. If two players tie, add three for every stone wall at your own village, two for a wooden wall and one for a straw wall and reduce that figure by the number of lava streams reaching your village. The higher number wins. 3d3428e81fc514ed804c0ec957d243fa1fbe1cc6 Gamehelpgearnpiston 0 112 2036 1992 2016-10-26T21:42:52Z Senatorhung 4176 /* GAME END */ wikitext text/x-wiki It is 1888, and everywhere you turn, people are talking about the horseless carriage. The players build an automobile prototype by patenting new parts, scavenging in the junk yard, and looking for opportunities to trip up their fellow automotive pioneers, all the while seeking to impress investors that are looking to get into car production. Gear & Piston is a simple, yet engaging 30-60 minute game for 2-6 players. ===QUICK RULES REFERENCE=== ====ROUND SEQUENCE AND PHASES==== *I. Place action tokens. (between I and II, you may discard ONE blueprint) *II. Resolve actions. *III. Refresh Patent Office (Location #3) and Junk Yard (Location #4). ====LOCATION ACTIONS==== *Back Alley (Location #2): *WARNING* The Action Token placed in the Back Alley cannot be used during the next planning phase. ** Choose 1 action from the following. <OL> # Black Market (draw 3 New Parts and keep 1)<BR> # Espionage (look at one player's blueprints and take one of them)<BR> # Union Muscle (move an Action Token ahead in another location)<BR> </OL><BR> *Patent Office (Location #3): Take 1 New Part, either from the face up parts or from the top of the stack. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Patent Office actions are wasted.<BR><BR> *Junk Yard (Location #4): Take up to 2 Junk Parts, either from the 3 face up parts or from the top of the stack. If a face up part is chosen, it is replaced before the second is chosen. You can only hold a maximum of 5 blueprints in hand, so if you already have 5 blueprints, any further Junk Yard actions are wasted.<BR><BR> *Workshop (Location #5): Actions that may be used are Build, Dismantle, and Upgrade. The FIRST action token placed in this location provides for 3 workshop actions. The SECOND action token placed in this location provides for 2 workshop actions. Every further action token at this location will only allow 1 workshop action. The last player to place an action token here will be the first player to act in the next round. ** Choose action(s) from the following. <OL> # Build (add 1 blueprint from your hand to either the front half or the back half of your automobile)<BR> # Dismantle (remove 1 part from your automobile and discard it)<BR> # Upgrade (replace ANY NUMBER of parts on your automobile with parts of the same type and colour from your hand)<BR> </OL><BR> ====REQUIREMENTS OF A COMPLETE AUTOMOBILE==== You start out building your automobile in 2 sections - the front and the back. At the end of the game, the 2 sections will be joined together. * Each automobile requires: <UL> # at least ONE engine (consists of a motor and at least one fuel tank of the same color);<BR> # at least ONE Gear;<BR> # at least TWO Axles; and<BR> # exactly ONE steering mechanism. </UL> Further Building Notes: * Every motor requires a matching fuel tank but there can be extra fuel tanks. * Colored improvements and fuel require an motor of same color. * Each part on the top row requires a part on the bottom row and vice versa. * All parts must be supported by an axle. Each Axle supports only the five parts surrounding it (3 above, 1 on either side). * There are bonus points at the end of the game for each player for their longest contiguous chain of parts of the same colour. ====GAME END==== *There are not enough tiles to refill a location from the refill Stack. OR *One of the players has a complete automobile with at least twelve parts on it (builder must click the 'join' icon in the workshop to join the 2 halves of the car). At the end of the game all players must join the two halves of the car and have a complete automobile. Players may need to complete their automobile by adding scrap. Illegal parts must either be covered up or have scrap added to make them legal. Each scrap acts as a single part. In the top row it can be a motor, fuel or steering. In the bottom row it can be an axle or a gear. The smallest complete auto is 6 pieces. Do not keep adding scrap to your vehicle if it would make your car longer than 9 or you risk crashing the game. If your car is that long and is incomplete there is an illegal part that must be covered up. ====SCORING==== * VP according to Investors The first investor cares about the number of each icon. If there are 0 or 1 of range, comfort or power it is worth no points. The first two range are worth 2 or 3, first two power and first two comfort are worth 1, 2 or 3, based on the investor's preference and each additional is always worth +2 VP regardless of the investor's preference. * +1 VP for each part of the same color (red, green, yellow or grey) in the largest continuous section. Each car will have at least 4 grey parts so its likely to be the dominant color. Scrap parts have no color. * -1 VP for each point of Volatility not countered by a wrench icon. ====BEGINNER TIPS==== * Keep an eye on what other players are doing. If three people are building the same color of engine it is going to be very hard for all of them to succeed. * Make sure to build often enough because you can hold a maximum of 5 blueprints at a time. Also if you aren't in the first two spots in the workshop you aren't going to get enough actions to finish your car. * It is advisable to visit the Junk Yard every now and then especially if there are some parts without Volatility for grabs. The junk yard also has only the 5 kinds of parts required to finish a vehicle so if you are missing a key part you are much more likely to find it here than blindly drawing from the patent office. * The game can end surprisingly fast and each Black Market action and blind draw from the Patent Office makes the game end even faster. * Remember that you can upgrade multiple junk parts with one workshop action. c44c237bee595c6f28eb95018d696438416ee03b Gamehelpkalah 0 162 2037 1112 2016-11-10T07:02:20Z Notched 14924 /* EQUIPMENT */ wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah. A player owns the six holes closest to him and the Kalah on his right side. The board is set up with the same number of stones (or seeds) in each round hole. The Kalah is empty at the start of the game. Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. ===OBJECT=== The object of the game is to capture more stones than one's opponent. ===RULES=== At the beginning of the game, from 3 to 6 stones are placed in each hole. Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has collected most stones in his/her Kalah is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== «Pie rule» - Second player can take opponent's first move and change sides of the board. «Empty Capture» - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' 1d26e91a8382617270628d79e01e0f0c016ab64c 2038 2037 2016-11-10T07:17:54Z Notched 14924 /* OBJECT */ wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah. A player owns the six holes closest to him and the Kalah on his right side. The board is set up with the same number of stones (or seeds) in each round hole. The Kalah is empty at the start of the game. Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. ===OBJECT=== The object of the game is to have more stones in your Kalah than your opponent does. There are three ways to put stones in your Kalah: 1) A player gets stones by placing them in regular movements into their Kalah one at a time). 2) Stones are captured by landing in your open space and your opponent has stones in the opposing hole. Stones from both holes are transfered to the Kalah.(the empty capture varient does not require the opponent to have stones in the opposing hole to claim the single stone) 3) When the opposing player has no stones on their side of the board and it is their turn to play, the game is over and all remaining stones go to your Kalah. This BGA game will end when 50% +1 stones are in a single player's Kalah ===RULES=== At the beginning of the game, from 3 to 6 stones are placed in each hole. Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has collected most stones in his/her Kalah is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== «Pie rule» - Second player can take opponent's first move and change sides of the board. «Empty Capture» - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' dc1e0adb17be2c4cd30400e69fa1207e9e81af01 2039 2038 2016-11-10T07:24:11Z Notched 14924 /* OBJECT */ wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah. A player owns the six holes closest to him and the Kalah on his right side. The board is set up with the same number of stones (or seeds) in each round hole. The Kalah is empty at the start of the game. Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. ===OBJECT=== The object of the game is to have more stones in your Kalah than your opponent does. Once a player 'Captures a stone in their Kalah, it it remains there for the rest of the game. There are three ways to put stones in your Kalah: 1) A player gets stones by placing them in regular movements into their Kalah (one at a time). 2) Stones are captured by landing in your open space and your opponent has stones in the opposing hole. Stones from both holes are transfered to the Kalah.(the empty capture varient does not require the opponent to have stones in the opposing hole to claim the single stone) 3) When the opposing player has no stones on their side of the board and it is their turn to play, the game is over and all remaining stones go Kalah on that side of the board. This BGA game will end when 50% +1 stones are in a single player's Kalah ===RULES=== At the beginning of the game, from 3 to 6 stones are placed in each hole. Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has collected most stones in his/her Kalah is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== «Pie rule» - Second player can take opponent's first move and change sides of the board. «Empty Capture» - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' dbba20f92c102209f055fa23dcf376e2ca75d82a 2040 2039 2016-11-10T07:35:27Z Notched 14924 /* COMMENT FROM THE DEVELOPER (stst) */ wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah. A player owns the six holes closest to him and the Kalah on his right side. The board is set up with the same number of stones (or seeds) in each round hole. The Kalah is empty at the start of the game. Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. ===OBJECT=== The object of the game is to have more stones in your Kalah than your opponent does. Once a player 'Captures a stone in their Kalah, it it remains there for the rest of the game. There are three ways to put stones in your Kalah: 1) A player gets stones by placing them in regular movements into their Kalah (one at a time). 2) Stones are captured by landing in your open space and your opponent has stones in the opposing hole. Stones from both holes are transfered to the Kalah.(the empty capture varient does not require the opponent to have stones in the opposing hole to claim the single stone) 3) When the opposing player has no stones on their side of the board and it is their turn to play, the game is over and all remaining stones go Kalah on that side of the board. This BGA game will end when 50% +1 stones are in a single player's Kalah ===RULES=== At the beginning of the game, from 3 to 6 stones are placed in each hole. Play is counterclockwise. On a turn, the player removes all stones from one of the holes under his/her control. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has collected most stones in his/her Kalah is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== «Pie rule» - Second player can take opponent's first move and change sides of the board. «Empty Capture» - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' THE FOLLOWING ARE NOTES FROM BGA PLAYERS This game is also known as Mankalah. There are several other variations of this game which are not in BGA such as: - No capture - Placing stones in both Kalah - Self capture by placing stones in an opponent's empty hole 4e0db5240741f14d259de2a4d697271e263f6524 2041 2040 2016-11-10T07:45:15Z Notched 14924 /* RULES */ wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah. A player owns the six holes closest to him and the Kalah on his right side. The board is set up with the same number of stones (or seeds) in each round hole. The Kalah is empty at the start of the game. Beginners may start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. ===OBJECT=== The object of the game is to have more stones in your Kalah than your opponent does. Once a player 'Captures a stone in their Kalah, it it remains there for the rest of the game. There are three ways to put stones in your Kalah: 1) A player gets stones by placing them in regular movements into their Kalah (one at a time). 2) Stones are captured by landing in your open space and your opponent has stones in the opposing hole. Stones from both holes are transfered to the Kalah.(the empty capture varient does not require the opponent to have stones in the opposing hole to claim the single stone) 3) When the opposing player has no stones on their side of the board and it is their turn to play, the game is over and all remaining stones go Kalah on that side of the board. This BGA game will end when 50% +1 stones are in a single player's Kalah ===RULES=== At the beginning of the game, the selected number of stones are in each hole (3 to 6). Each hole has the same number. Play is always counterclockwise. On a turn, the player removes all stones from the selected hole on their half of the board. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. Under the "Pie Rule" variation, once the first player completes their initial move, the second player has the option to choose take their opponent's position. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has collected most stones in his/her Kalah is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== «Pie rule» - Second player can take opponent's first move and change sides of the board. «Empty Capture» - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' THE FOLLOWING ARE NOTES FROM BGA PLAYERS This game is also known as Mankalah. There are several other variations of this game which are not in BGA such as: - No capture - Placing stones in both Kalah - Self capture by placing stones in an opponent's empty hole 6e430395d48f910559a213c3cfcd73e6c935e24c 2042 2041 2016-11-10T07:47:34Z Notched 14924 /* EQUIPMENT */ wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah. A player owns the six holes closest to him and the Kalah on his right side. The board is set up with the same number of stones (or seeds) in each round hole. The Kalah is empty at the start of the game. Beginners may want to start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. Traditionally the game play is most associated with 4 stones. ===OBJECT=== The object of the game is to have more stones in your Kalah than your opponent does. Once a player 'Captures a stone in their Kalah, it it remains there for the rest of the game. There are three ways to put stones in your Kalah: 1) A player gets stones by placing them in regular movements into their Kalah (one at a time). 2) Stones are captured by landing in your open space and your opponent has stones in the opposing hole. Stones from both holes are transfered to the Kalah.(the empty capture varient does not require the opponent to have stones in the opposing hole to claim the single stone) 3) When the opposing player has no stones on their side of the board and it is their turn to play, the game is over and all remaining stones go Kalah on that side of the board. This BGA game will end when 50% +1 stones are in a single player's Kalah ===RULES=== At the beginning of the game, the selected number of stones are in each hole (3 to 6). Each hole has the same number. Play is always counterclockwise. On a turn, the player removes all stones from the selected hole on their half of the board. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. Under the "Pie Rule" variation, once the first player completes their initial move, the second player has the option to choose take their opponent's position. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has collected most stones in his/her Kalah is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== «Pie rule» - Second player can take opponent's first move and change sides of the board. «Empty Capture» - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' THE FOLLOWING ARE NOTES FROM BGA PLAYERS This game is also known as Mankalah. There are several other variations of this game which are not in BGA such as: - No capture - Placing stones in both Kalah - Self capture by placing stones in an opponent's empty hole 0d3d6dd89cac284a8f838d155fbce499585bc73e 2043 2042 2016-11-10T07:49:35Z Notched 14924 /* OBJECT */ wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah. A player owns the six holes closest to him and the Kalah on his right side. The board is set up with the same number of stones (or seeds) in each round hole. The Kalah is empty at the start of the game. Beginners may want to start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. Traditionally the game play is most associated with 4 stones. ===OBJECT=== The object of the game is to have more stones in your Kalah than your opponent does. Once a player 'Captures a stone in their Kalah, it it remains there for the rest of the game. There are three ways to put stones in your Kalah: 1) A player gets stones by placing them in regular movements into their Kalah (one at a time). 2) Stones are captured by landing in your open space and your opponent has stones in the opposing hole. Stones from both holes are transfered to the Kalah.(the empty capture varient does not require the opponent to have stones in the opposing hole to claim the single stone) 3) When a player has no stones on their side of the board and it is their turn to play, the game is over and all remaining stones go Kalah on that side of the board they are on. This BGA game will end when 50% +1 stones are in a single player's Kalah ===RULES=== At the beginning of the game, the selected number of stones are in each hole (3 to 6). Each hole has the same number. Play is always counterclockwise. On a turn, the player removes all stones from the selected hole on their half of the board. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. Under the "Pie Rule" variation, once the first player completes their initial move, the second player has the option to choose take their opponent's position. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has collected most stones in his/her Kalah is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== «Pie rule» - Second player can take opponent's first move and change sides of the board. «Empty Capture» - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' THE FOLLOWING ARE NOTES FROM BGA PLAYERS This game is also known as Mankalah. There are several other variations of this game which are not in BGA such as: - No capture - Placing stones in both Kalah - Self capture by placing stones in an opponent's empty hole 7a010cba8617d8cd45c970981f7f0a5feed36a0e 2044 2043 2016-11-10T07:51:10Z Notched 14924 /* COMMENT FROM THE DEVELOPER (stst) */ wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah. A player owns the six holes closest to him and the Kalah on his right side. The board is set up with the same number of stones (or seeds) in each round hole. The Kalah is empty at the start of the game. Beginners may want to start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. Traditionally the game play is most associated with 4 stones. ===OBJECT=== The object of the game is to have more stones in your Kalah than your opponent does. Once a player 'Captures a stone in their Kalah, it it remains there for the rest of the game. There are three ways to put stones in your Kalah: 1) A player gets stones by placing them in regular movements into their Kalah (one at a time). 2) Stones are captured by landing in your open space and your opponent has stones in the opposing hole. Stones from both holes are transfered to the Kalah.(the empty capture varient does not require the opponent to have stones in the opposing hole to claim the single stone) 3) When a player has no stones on their side of the board and it is their turn to play, the game is over and all remaining stones go Kalah on that side of the board they are on. This BGA game will end when 50% +1 stones are in a single player's Kalah ===RULES=== At the beginning of the game, the selected number of stones are in each hole (3 to 6). Each hole has the same number. Play is always counterclockwise. On a turn, the player removes all stones from the selected hole on their half of the board. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. Under the "Pie Rule" variation, once the first player completes their initial move, the second player has the option to choose take their opponent's position. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has collected most stones in his/her Kalah is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== «Pie rule» - Second player can take opponent's first move and change sides of the board. «Empty Capture» - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' THE FOLLOWING ARE NOTES FROM BGA PLAYERS This game is also known as Mankalah. There are several other variations of this game which are not in BGA such as: - No capture - Placing stones in both Kalah - Self capture by placing stones in an opponent's empty hole - No counters in the holes to indicate number on stones in them. ae0fd3b43a2378c6333645943b59c0165bb8b630 2045 2044 2016-11-10T07:55:51Z Notched 14924 /* VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME) */ wikitext text/x-wiki ===EQUIPMENT=== Kalah is played on a board of two rows, each consisting of six round holes that have a large store at either end called Kalah. A player owns the six holes closest to him and the Kalah on his right side. The board is set up with the same number of stones (or seeds) in each round hole. The Kalah is empty at the start of the game. Beginners may want to start with three stones in each hole, but the game becomes more and more challenging by starting with 4, 5 or up to 6 stones in each hole. Traditionally the game play is most associated with 4 stones. ===OBJECT=== The object of the game is to have more stones in your Kalah than your opponent does. Once a player 'Captures a stone in their Kalah, it it remains there for the rest of the game. There are three ways to put stones in your Kalah: 1) A player gets stones by placing them in regular movements into their Kalah (one at a time). 2) Stones are captured by landing in your open space and your opponent has stones in the opposing hole. Stones from both holes are transfered to the Kalah.(the empty capture varient does not require the opponent to have stones in the opposing hole to claim the single stone) 3) When a player has no stones on their side of the board and it is their turn to play, the game is over and all remaining stones go Kalah on that side of the board they are on. This BGA game will end when 50% +1 stones are in a single player's Kalah ===RULES=== At the beginning of the game, the selected number of stones are in each hole (3 to 6). Each hole has the same number. Play is always counterclockwise. On a turn, the player removes all stones from the selected hole on their half of the board. Moving counter-clockwise, the player drops one stone in each hole in turn, including the player's own Kalah but not his/her opponent's Kalah. Under the "Pie Rule" variation, once the first player completes their initial move, the second player has the option to choose take their opponent's position. If the last stone is dropped into an opponent's hole or a non-empty hole of the player, the move ends without anything being captured. If the last stone falls into the player's Kalah, he must move again. If the last stone is put into an empty hole owned by the player, he captures all stones of the opposite hole together with the capturing stone and puts them in his/her Kalah. If the opposite hole is empty, nothing is captured. A capture ends the move. ===END OF THE GAME=== The game ends: When a player, at his turn, is unable to move, because his no longer has any stones in any of his holes. The remaining stones are captured by his opponent. OR When a player collected more half of all stones in his/her Kalah. The player who has collected most stones in his/her Kalah is declared the winner. ===VARIATIONS (OPTION OF THIS ADAPTATION OF THE GAME)=== «Pie rule» - Second player can take opponent's first move and change sides of the board. «Empty Capture» - This variant permits to capture the last stone when landing in an empty hole on the player's own side even when the opposite hole of the opponent is empty. 《Stones》 - This varient allows a game to start with 3, 4, 5 or 6 stones in each of the 12 holes. ===COMMENT FROM THE DEVELOPER (stst)=== '''THESE RULES ARE USED AT THIS ADAPTATION OF THE GAME''' THE FOLLOWING ARE NOTES FROM BGA PLAYERS This game is also known as Mankalah. There are several other variations of this game which are not in BGA such as: - No capture - Placing stones in both Kalah - Self capture by placing stones in an opponent's empty hole - No counters in the holes to indicate number on stones in them. ab052344e67e6d8b96017456397bf78ce561fb91 Kaozeadenn Implijer:Notched 3 238 2046 2016-11-10T07:59:35Z Notched 14924 /* RULES */ wikitext text/x-wiki Everyone likes Notched. That darn Canucks is the best! 388cf04e0997e78e1538f1c0ee88814754f285ff Help 0 4 2047 1783 2016-11-12T09:45:13Z Hey teacher 6378 /* Games */ + Eruption wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] is the most complete source of help for BGA. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpsechsnimmt|6 Nimmt!]] * [[Gamehelpeightmastersrevenge|8 Master's Revenge]] * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpassyria|Assyria]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpbattleoflits|Battle of LITS]] * [[Gamehelpbombay|Bombay]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcheckers|Checkers]] * [[Gamehelpchess|Chess]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpcoltexpress|Colt Express]] * [[Gamehelpdarkagent|Dark Agent]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpelfenland|Elfenland]] * [[Gamehelpakeruption|Eruption]] * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] </td> <td valign="top"> * [[Gamehelpflorenzacardgame|Florenza: The Card Game]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphanabi|Hanabi]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpinjawara|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpk2|K2]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] * [[Gamehelpkeyflower|Keyflower]] * [[Gamehelpkoikoi|Koi-koi]] * [[Gamehelpkoryo|Koryŏ]] * [[Gamehelpledernierpeuple|Le Dernier Peuple]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelplordsofxidit|Lords of Xidit]] * [[Gamehelplostcities|Lost Cities]] </td> <td valign="top"> * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpmetromania|Metromania]] * [[Gamehelpnautilus|Nautilus]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpnoirkvi|Noir: Killer versus Inspector]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppolis|Polis: Fight for the Hegemony]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquantum|Quantum]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelptashkalar|Tash-Kalar]] </td> <td valign="top"> * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpcarrara|The Palaces of Carrara]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpxiangqi|Xiangqi]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> 1ee25baae5abea0decd705b4cc458d5a635bf672 2050 2047 2016-11-13T18:15:29Z Victoria la 11989 /* Games */ wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] is the most complete source of help for BGA. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpsechsnimmt|6 Nimmt!]] * [[Gamehelpeightmastersrevenge|8 Master's Revenge]] * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpassyria|Assyria]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpbattleoflits|Battle of LITS]] * [[Gamehelpbombay|Bombay]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcheckers|Checkers]] * [[Gamehelpchess|Chess]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpcoltexpress|Colt Express]] * [[Gamehelpdarkagent|Dark Agent]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpelfenland|Elfenland]] * [[Gamehelpakeruption|Eruption]] * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] </td> <td valign="top"> * [[Gamehelpflorenzacardgame|Florenza: The Card Game]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphanabi|Hanabi]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpinjawara|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpk2|K2]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] * [[Gamehelpkeyflower|Keyflower]] * [[Gamehelpkoikoi|Koi-koi]] * [[Gamehelpkoryo|Koryŏ]] * [[Gamehelpledernierpeuple|Le Dernier Peuple]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelplordsofxidit|Lords of Xidit]] * [[Gamehelplostcities|Lost Cities]] </td> <td valign="top"> * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpmetromania|Metromania]] * [[Gamehelpmadeira|Madeira]] * [[Gamehelpnautilus|Nautilus]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpnoirkvi|Noir: Killer versus Inspector]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppolis|Polis: Fight for the Hegemony]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquantum|Quantum]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelptashkalar|Tash-Kalar]] </td> <td valign="top"> * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpcarrara|The Palaces of Carrara]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpxiangqi|Xiangqi]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> 0190c8d43cf9287157fd4ad3c8581373b58568dc 2051 2050 2016-11-13T18:16:25Z Victoria la 11989 /* Games */ wikitext text/x-wiki An issue? A question? * [[Faq|Frequently asked questions]] is the most complete source of help for BGA. * [http://forum.boardgamearena.com Forums] are also helpful to get information. == Help contents == * [[Faq|Frequently asked questions]] * [[About Board Game Arena|About Board Game Arena]] ** [[About us|About us]] ** [[Club Board Game Arena|Club Board Game Arena]] ** [[Contact us|Contact us]] === Detailed help === * [[Getting started|Getting started]] * [[Browser support|Browser support]] * [[Moderation and grades|Moderation and grades]] * [[Game clock|Game clock]] * [[Rating|Rating]] * [[Reputation|Reputation]] * [[Translation guidelines|Translation guidelines]] == Games == Game names which are displayed in red still need game help/summaries written for them. So help out and write one for them by creating a new page for these games. To do so simply click on them below, this will direct you to a page creation page. <table cellpadding="0" cellspacing="5" border="0"> <tr> <td valign="top"> '''Available on BGA''' * [[Gamehelpsechsnimmt|6 Nimmt!]] * [[Gamehelpeightmastersrevenge|8 Master's Revenge]] * [[Gamehelpamyitis|Amyitis]] * [[Gamehelparmadora|Armadöra]] * [[Gamehelpassyria|Assyria]] * [[Gamehelpbackgammon|Backgammon]] * [[Gamehelpbattlesheep|Battle Sheep]] * [[Gamehelpbattleoflits|Battle of LITS]] * [[Gamehelpbombay|Bombay]] * [[Gamehelpcantstop|Can't Stop]] * [[Gamehelpcaylus|Caylus]] * [[Gamehelpcheckers|Checkers]] * [[Gamehelpchess|Chess]] * [[Gamehelpchinagold|China Gold]] * [[Gamehelpcinco|Cinco]] * [[Gamehelpcolorpop|Color Pop]] * [[Gamehelpcoloretto|Coloretto]] * [[Gamehelpcoltexpress|Colt Express]] * [[Gamehelpdarkagent|Dark Agent]] * [[Gamehelpdiams|Diam's]] * [[Gamehelpdragonline|Dragon Line]] * [[Gamehelpdragonheart|Dragonheart]] * [[Gamehelpelfenland|Elfenland]] * [[Gamehelpakeruption|Eruption]] * [[Gamehelpnorthwestpassage|Expedition: Northwest Passage]] </td> <td valign="top"> * [[Gamehelpflorenzacardgame|Florenza: The Card Game]] * [[Gamehelpgearnpiston|Gear & Piston]] * [[Gamehelpgomoku|Gomoku]] * [[Gamehelpgosu|Gosu]] * [[Gamehelpgyges|Gygès]] * [[Gamehelphaggis|Haggis]] * [[Gamehelphawaii|Hawaii]] * [[Gamehelphanabi|Hanabi]] * [[Gamehelphearts|Hearts]] * [[Gamehelphex|Hex]] * [[Gamehelphive|Hive]] * [[Gamehelpintheyearofthedragon|In the Year of the Dragon]] * [[Gamehelpinjawara|Injawara]] * [[Gamehelpjaipur|Jaipur]] * [[Gamehelpk2|K2]] * [[Gamehelpkahuna|Kahuna]] * [[Gamehelpkalah|Kalah]] * [[Gamehelpkeyflower|Keyflower]] * [[Gamehelpkoikoi|Koi-koi]] * [[Gamehelpkoryo|Koryŏ]] * [[Gamehelpledernierpeuple|Le Dernier Peuple]] * [[Gamehelplibertalia|Libertalia]] * [[Gamehelplordsofxidit|Lords of Xidit]] * [[Gamehelplostcities|Lost Cities]] </td> <td valign="top"> * [[Gamehelpmachiavelli|Machiavelli]] * [[Gamehelpmetromania|Metromania]] * [[Gamehelpmadeira|Madeira]] * [[Gamehelpnautilus|Nautilus]] * [[Gamehelpneutreeko|Neutreeko]] * [[Gamehelpniagara|Niagara]] * [[Gamehelpnoirkvi|Noir: Killer versus Inspector]] * [[Gamehelpdudo|Perudo]] * [[Gamehelppolis|Polis: Fight for the Hegemony]] * [[Gamehelppuertorico|Puerto Rico]] * [[Gamehelppylos|Pylos]] * [[Gamehelpquarto|Quarto]] * [[Gamehelpquantum|Quantum]] * [[Gamehelpquoridor|Quoridor]] * [[Gamehelpraceforthegalaxy|Race for the Galaxy]] * [[Gamehelpreversi|Reversi]] * [[Gamehelpsaboteur|Saboteur]] * [[Gamehelpseasons|Seasons]] * [[Gamehelpsenet|Senet]] * [[Gamehelpsobek|Sobek]] * [[Gamehelpspyrium|Spyrium]] * [[Gamehelpstoneage|Stone Age]] * [[Gamehelptakenoko|Takenoko]] * [[Gamehelptargi|Targi]] * [[Gamehelptashkalar|Tash-Kalar]] </td> <td valign="top"> * [[Gamehelptheboss|The Boss]] * [[Gamehelpthejellymonsterlab|The Jelly Monster Lab]] * [[Gamehelpcarrara|The Palaces of Carrara]] * [[Gamehelpthermopyles|Thermopyles]] * [[Gamehelpthroughtheages|Through the Ages]] * [[Gamehelptimemasters|Time Masters]] * [[Gamehelptobago|Tobago]] * [[Gamehelptokaido|Tokaido]] * [[Gamehelptournay|Tournay]] * [[Gamehelptroyes|Troyes]] * [[Gamehelptwintinbots|Twin Tin Bots]] * [[Gamehelptzolkin|Tzolk'in]] * [[Gamehelpunclechestnuttablegype|Uncle Chesnut's Table Gype]] * [[Gamehelpunitedsquare|United Square]] * [[Gamehelpxiangqi|Xiangqi]] * [[Gamehelpyatzy|Yahtzee]] </td> <td valign="top"> '''Removed from BGA''' * [[Gamehelpdominion|Dominion]] </td> </tr> </table> f0eaaa94d9836ae1cf496203583a11ef754a4d9f Gamehelpkqj 0 239 2049 2016-11-13T07:22:50Z Le jack 14961 Created page with ""KQJ" refers to 3 cards: King, Queen and Jack. Adapted from "Belote" and "Coinche", this french card game is born from the desire to play up to 6 people, other folds games o..." wikitext text/x-wiki "KQJ" refers to 3 cards: King, Queen and Jack. Adapted from "Belote" and "Coinche", this french card game is born from the desire to play up to 6 people, other folds games often stopping to 4. The '''KQJ''' can be played: - 6, with 2 or 3 teams, 5, 4 or 3, - With or without "Random Partners" - With or without "All-Trumps/No-Trump" - With or without "Combinations" - With or without "Auctions". Beyond the number of players, it is possible to combine all variants according to your preferences. On '''Board Game Arena''', the '''KQJ''' can be played currently: - 6, with 2 or 3 teams, - With or without "Random Partners" - With "All-Trumps/No-Trump" only, - Without "Combinations" only, - With or without "Auctions". If you need clarification, if you want to develop the missing variants, if you want to buy the game, or else, you can contact us directly by email: '''kaquji@gmail.com'''. == The KQJ Rules on Board Game Arena == The rules that follow are for 6 players with 2 teams, without random partners and without auctions. The rules of the other playable variants on '''Board Game Arena''' are described in the Variants. === Principles === ---- The '''KQJ''' is a game of folds in several rounds. - A Round is the deal of cards to each player and all folds up to the exhaustion of the cards. - A Fold is a batch of cards made of one card from each player, it is won by the one who plays the "Master" card. - The "Master" card of a fold is the highest card of the requested series or the highest Trump card if any. - Each card of the fold has a value: added to the others, it allows to determine the winner of the Round. Before the start of the game, players must agree on certain points of the rules. For example, they can choose the variants to play or the endgame conditions. === Goal of the game to choose === ---- The team that exceeds the score to achieve wins: 500 pts or 1000 pts or 2000 pts! === Game preparation === ---- When launching the game, players place around the table randomly. 2 teams are formed. Everyone is placed between two players of the other team. The players of the same team are "partners". You always play clockwise. === Beginning of a Round === ---- On '''Board Game Arena''', a "Dealer" token is used. Whoever arbitrarily received the token "Dealer" at the formation of the teams is the first Dealer. His left is the Opener. ==== Deal Beginning ==== The cards are mixed. Each player is dealt 5 cards and can watch them in his/her hand. Then another card is dealed and revealed in the middle of the table: the Return. ==== The Contract ==== Each team must make more points than the opposing team. His/her turn, each player can "take": choose the Trump according to his/her cards in hand! During the first lap each player can, starting with the Opener: - Say "Pass" and defer to the next player, - Or Take '''choosing the suit of the Return''' as the Trump. For example, "Spade" if the Return is a spade. If all players have passed, then there is a 2nd lap and each player can: - Say "Pass" again, - Or Take '''choosing Trump in the suit of his/her choice (even the suit of the Return)'''. The '''KQJ''' is played on '''Board Game Arena''' with All-Trumps/No-Trump. Normally the Trump is one of the 4 suits. Here each player can also decide that: - All suits are Trumps: "ALL-TRUMPS". - No suit is Trump: "NO-TRUMP". If everyone pass 2 times, the round is closed. The Opener becomes the Dealer... On the other hand, if a player Takes, he/she becomes the Sender, his/her team becomes the contracting team, the other team becomes the defending team. ==== Deal Ending ==== Once a player Takes, he/she collects the Return in his/her hand. Then each player receives 3 cards, unless the Sender who receives only 2 cards (he/she took the Return). At the end of the Deal, each player has 8 cards in his/her hand. === Folds Forming === ---- ==== Rules and Principles ==== The Opener starts the 1rst Fold and put at the table center a card from his/her hand face up. Then, his/her turn, each player must play one of his/her cards face up. The one who starts may play any card from his/her hand, the suit of this card is the "requested" suit. The other players follow the rules below: - '''When you possess the requested suit''' --- You must '''play a card of the suit''' and if the Trump is requested, if possible, you must '''play a Trump card that beats all previous ones'''. - '''When you don't possess the requested suit and if a partner is "Master"''' --- You can '''play any card of your choice''', --- Or, in order to become "Master", you can '''Trump''' (play a Trump card) or '''Over-trump''' if someone has already played a Trump card. - '''When you don't possess the required series and if the opposing team is "Master"''' --- If you can become "Master" you must '''Trump''' or '''Over-trump''', --- If you can't become "Master", we can '''play any card of your choice'''. '''3 principles to determine the "Master" card''': - The Trump prevails against normal suits. - Among the suits of the same rank, the requested suit wins. - In the same suit, the card of higher rank wins. {|class="wikitable alternance centre" |+ Normal suits |- ! scope="row" width=16% | <center>Rank</center> | width=7% align="center" | A | width=7% align="center" | 10 | width=7% align="center" | H | width=7% align="center" | K | width=7% align="center" | Q | width=7% align="center" | J | width=7% align="center" | 9 | width=7% align="center" | 8 | width=7% align="center" | 7 | width=7% align="center" | 6 | width=7% align="center" | 5 | width=7% align="center" | 4 |- ! scope="row" | <center>Value</center> | align="center" | 12 pts | align="center" | 10 pts | align="center" | 7 pts | align="center" | 5 pts | align="center" | 4 pts | align="center" | 3 pts | align="center" | 2 pts | align="center" | 1 pt | align="center" | 0 pt | align="center" | 0 pt | align="center" | 0 pt | align="center" | 0 pt |} {|class="wikitable alternance centre" |+ The Trump |- ! scope="row" width=16% | <center>Rank</center> | width=7% align="center" | 9 | width=7% align="center" | 8 | width=7% align="center" | 7 | width=7% align="center" | A | width=7% align="center" | 10 | width=7% align="center" | H | width=7% align="center" | K | width=7% align="center" | Q | width=7% align="center" | J | width=7% align="center" | 6 | width=7% align="center" | 5 | width=7% align="center" | 4 |- ! scope="row" | <center>Value</center> | align="center" | 27 pts | align="center" | 22 pts | align="center" | 14 pts | align="center" | 12 pts | align="center" | 10 pts | align="center" | 7 pts | align="center" | 5 pts | align="center" | 4 pts | align="center" | 3 pts | align="center" | 0 pt | align="center" | 0 pt | align="center" | 0 pt |} The sum of the points is (3 x 44 pts) + 104 pts = 236 pts. When round is played '''with "All-Trumps" or "No-Trump" all suits are of same rank''' and the cards values are changed. {|class="wikitable alternance centre" |+ NO-TRUMP (4 suits) |- ! scope="row" width=16% | <center>Rank</center> | width=7% align="center" | A | width=7% align="center" | 10 | width=7% align="center" | H | width=7% align="center" | K | width=7% align="center" | Q | width=7% align="center" | J | width=7% align="center" | 9 | width=7% align="center" | 8 | width=7% align="center" | 7 | width=7% align="center" | 6 | width=7% align="center" | 5 | width=7% align="center" | 4 |- ! scope="row" | <center>Value</center> | align="center" | 20 pts | align="center" | 17 pts | align="center" | 7 pts | align="center" | 5 pts | align="center" | 4 pts | align="center" | 3 pts | align="center" | 2 pts | align="center" | 1 pt | align="center" | 0 pt | align="center" | 0 pt | align="center" | 0 pt | align="center" | 0 pt |} {|class="wikitable alternance centre" |+ ALL-TRUMPS (4 suits) |- ! scope="row" width=16% | <center>Rank</center> | width=7% align="center" | 9 | width=7% align="center" | 8 | width=7% align="center" | 7 | width=7% align="center" | A | width=7% align="center" | 10 | width=7% align="center" | H | width=7% align="center" | K | width=7% align="center" | Q | width=7% align="center" | J | width=7% align="center" | 6 | width=7% align="center" | 5 | width=7% align="center" | 4 |- ! scope="row" | <center>Value</center> | align="center" | 17 pts | align="center" | 14 pts | align="center" | 7 pts | align="center" | 6 pts | align="center" | 5 pts | align="center" | 4 pts | align="center" | 3 pts | align="center" | 2 pts | align="center" | 1 pt | align="center" | 0 pt | align="center" | 0 pt | align="center" | 0 pt |} With "All-Trumps" or "No-Trump", the sum of the points is 4 x 59 pts = 236 pts. When a Fold is finished, the one who played the "Master" card wins, puts the fold with hidden face in front of him/her and begins the next fold. When players have no card in hand anymore, it is '''the end of the round''' (see below). ==== Folds Examples ==== '''Alicia''', '''Cindy''' and '''Elena''' play against '''Billy''', '''Dylan''' and '''Frank'''. '''Frank''' deals. '''Billy''' takes with Heart as Trump. '''Alicia''' opens with her Ace of Club. In the same suit, '''Billy''' has the 4 of Club. He has to play it. Others each plays a card of the requested suit: '''Alicia''' wins the 1st fold. '''Alicia''' begins the 2nd fold with her 10 of Club. '''Billy''' has no more Club card, he trumps: 6 of Heart. '''Cindy''' must trump. She over-trumps: Hero of Heart. '''Dylan''' should trump too. But he has the 5 of Heart, so he can not play a Trump card that beats the Hero of '''Cindy'''. He plays any card of his choice: 4 of Spade. '''Elena''' has no more Club card, she could over-trump with her 7 of Heart, but her partner '''Cindy''' is the Master. She plays any card of her choice: 10 of Spade. '''Frank''' has the Hero of Club, he must play a card of the requested suit. So '''Cindy''' wins the 2nd Fold with the Hero of Heart. She begins the 3rd Fold. === Bonuses === ---- A Bonus is an event, announced or not, which matches with a number of points that a team will add to its folds points: '''The Bonuses help to fulfill the Contract'''. - '''The Ten additional''': 10 pts which are '''always''' awarded to the team that wins the last fold. - '''The Capot''': 154 pts awarded to a team if it wins all the folds. - '''The KQ''': 20 pts for the team of the player who has anounced "KQ" during the round. The bonus is validated if: --- A player had the Trump cards King (K) and Queen (Q) in his/her hand, --- These cards have been played in this order: the King then the Queen, --- This player has said "K" playing the King and "KQ" playing the Queen. - '''The KQJ''': 50 pts for the team of the player who has announced "KQJ" during the round. The bonus is validated if: --- A player had the 3 Trump cards King (K), Queen (Q) and Jack (J) in his/her hand, --- These cards have been played in this order: the King then the Queen then the Jack, --- This player has said "K" playing the King, "KQ" playing the Queen and finally "KQJ" playing the Jack. KQ provides no point when there is a KQJ. When the round is played with "All-Trumps," there are 4 feasible KQ or KQJ. On '''Board Game Arena''', the "K", "KQ" and "KQJ" announcements are done automatically. === End of a Round === ---- ==== The Points Account ==== When the last fold is picked up, the values of the cards in the folds of each team are totaled. Then bonuses are added to the scores of the teams that have won some. At least, one of the teams wins the Ten additional. '''The team with the most points at that time, fulfills the contract and wins the round!''' ==== The Scoring ==== Only the team that fulfills the contract scores its points rounded to the nearest ten: - The totals which end between 1 and 4 are rounded to the under nearest ten (154 becomes 150). - The totals which end between 5 and 9 are rounded to the upper nearest ten (155 becomes 160). Finally, scores are added to previous scores. ==== New Deal ==== In the next round, Opener (left of the Dealer) becomes the new Dealer. He/she collects the "Dealer" token. === Gratuities === ---- A gratuity is a number of points that are obtained under certain conditions and that are added to scores. '''Gratuities are not taken into account to win the contract.''' ==== The Litigation ==== In case of a tie (123 pts, 133 pts if KQ or 148 pts if KQJ), there is Litigation and no team scores. Litigation generates a "Litigation Gratuity" for the next round with a value which is equal to the rounding of the score (120 pts, 130 pts if KQ or 150 pts if KQJ). It will be added to the score of the team that will win the next round. If there is again a Litigation, the first gratuity is lost. === End of the Game === ---- In general, a game of '''KQJ''' is played in 1000 pts. Once a team reaches or exceeds 1000 pts at the end of a round, the game is over: this team wins! However, when creating the game on '''Board Game Arena''', players can choose a different score to reach: 500 points or 2000 pts. == Variants on Board Game Arena == === 6 players with 3 teams === ---- ==== Game Preparation ==== The three teams are now composed of two partners. Partners of the same team are facing each other, with neighbor players from each of two other teams. ==== The Contract ==== The team from the Sender must get more points than the best two other teams (defending team). ==== The Points Account ==== You have to count the points in the folds of each of the three teams. ==== The Scoring ==== - If the contractor team has a higher score than each of the other 2 teams: the Contract is "Successful", the contractor team scores the rounding of its points. - If at least one defending team has a higher score than the contractor team: the Contract is "Failed", each defending team scores the rounding of its own points. - In case of tie between the contracting team and the best defending team, there is "Litigation" and no team scores (see "'''Gratuities'''" section above). ==== The Account Gratuities ==== These special gratuities depend on the teams folds number and value before bonuses. - If a team gets 20 points or less with one fold or more, then the 2 other teams get a gratuity of 20 points. - If one team wins no fold, then the 2 other teams get a gratuity of 60 pts. === Random Partners === ---- ''This variant enables new strategies to succeed at the game.'' ==== Game Preparation ==== A ''KQJ''' Game with "Random Partners" is played each for oneself. Before starting, each player place is randomly determined and will remain the same for the entire game. ==== Beginning of a Round ==== At the beginning of each round, the partners are determined in random manner. ==== The Scoring ==== For each player you score the points his/her team has won. === Auctions === ---- ''More tension in the game.''' To play with auctions, retain all the specificities related to the chosen variants and to the number of teams. ==== The Deal ==== All the cards are dealed, without the intermediary Return card. ==== The Contract ==== Starting with the Opener and in turn, each player can: - Say "Pass" and defer to the next player, - Or Bid (or Outbid if there was a first bid) by declaring a contract that he/she agrees to do. He announces a points "Amount" (pack of 10) and the Trump he would choose. He/she may also announce "Capot" (optional). For example, "150 spade" or "400 Capot diamond". If no Contract is announced during the first auctions lap, the round is closed. The first auction is at least equal to 120 points (except to 6 players with 3 teams: minimum 80 pts). In case of higher auction, the new announced amount must be greater than the previous one. A player can outbid when his/her turn returns, even if he/she has "passed" before. "Capot" is an optional declaration: the player who announces it undertakes to win all the Folds (with the help of his/her partners). When "Capot" is announced, Auctions are closed. If after a player auction all others have passed, this player becomes the Sender and auctions are closed. When a contract is announced, if an opponent thinks it will not be realized, he/she can "Counter". On '''Board Game Arena''', automatically, this player says "Counter" and gets the One-sword token. In response, if desired, any player of the contracting team can "Overcounter". On '''Board Game Arena''', automatically, this player says "Overcounter" and gets the Two-swords token. Auctions are closed in case of Counter or Overcounter. The Sender's team must fulfill his/her contract. It must reach at least the announced amount. Futhermore it must win all the folds if "Capot" has been announced. ==== The Scoring ==== - If the Contract is "Successful", the contractor team scores the Contract Amount (even if it achieved more points than this amount). - If the Contract is "Failed", the defending teams score the Contract Amount. '''In case of Counter, score is doubled.''' '''In case of Overcounter, it is quadrupled.''' 9d401d4f9082afd83d3a295048b5ed283b4e82df Gamehelpcaylus 0 37 2052 704 2016-11-15T21:39:07Z Nandblock 11082 wikitext text/x-wiki == 1: INCOME == Each player receives 2 deniers, plus 1 denier per residence owned, 1 denier if they own the Library, and 2 deniers if they own the Hotel. == 2: PLACE WORKERS == Players in turn either place a worker or pass, in the order dictated by the turn order track, until everyone has passed. Placement may be on any unoccupied place or building on the board. If it is a building owned by another player, that player receives 1 VP. If it is your own building, or if you have a worker in the Inn's rightmost spot, pay 1 denier. Otherwise, pay the lowest unoccupied number on the bridge. [EXCEPTION: in 2-player Caylus, pay 3 deniers, not 2, once the other player passes.] Payments go to the bank, not other players. Passing: place a marker on the lowest number on the Bridge. If you are first to pass, gain 1 denier. == ACTIVATE PLACES BEFORE THE BRIDGE == Beginning with the Gate, any place with a worker is activated, and the worker returns to the player. GATE: Move the worker to any unoccupied place on the board for free. If it is a building owned by another player, they earn 1 VP. TRADING POST: Gain 3 deniers. MERCHANTS' GUILD: Move the provost up to 3 squares forward or back, for free. JOUSTING FIELD: Pay 1 denier + 1 cloth to earn a royal favour. STABLES: Move your marker to the indicated number in the turn order track; all players not in the Stables move down the turn order accordingly. INN: If your worker is on the left spot, move it to the right spot and return any worker there to its owner. If you are in the right spot, you can either leave your worker there or reclaim it. == 4: THE BRIDGE == In order of passing, from first to last, players may move the Provost forward or back, for one denier per square, to a maximum of 3 squares. == 5. ACTIVATE BUILDINGS == Past the bridge, in order, buildings with workers are activated, and the worker is returned to the player. Workers on buildings beyond the Provost are returned without activating those buildings. Notes on some buildings: Production: The 3 stone production buildings when activated by another player also grant one resource to the owner, chosen from the options in brackets. Construction: The Carpenter allows you to construct wood buildings; the Mason, stone buildings. The Lawyer changes a neutral building or one you own into a residence, for 1 denier + 1 cloth. (You cannot transform the Lawyer or a prestige building.) The Architect permits you to construct a prestige building over one of your residences. Constructing a building requires the resources listed on its card. (A white cube = any resource.) When a building is constructed, score the VPs indicated in its top right corner (residences are always 2 VPs). Some buildings also grant a royal favour (Church, Statue, etc.); the Monument grants 2 royal favours. If you build over a building with a worker on it, the transformation is postponed until after the worker's action. == 6. BUILD THE CASTLE == In the order that workers were placed in the castle, each player builds as many units as they like. A unit costs 3 different resources, of which one must be food. If you have a worker in the castle but do not construct a unit, lose 2 VPs. Each unit is worth VPs as follows: 5 VPs for the Dungeon, 4 VPs for the Walls, 3 VPs for the Towers. Each section is built in order (Dungeon, Walls, Towers). After a section marker is passed on the road, work continues in the next section even if the previous one is incomplete. If a section is filled, work immediately commences on the next section. The player who constructs the most units in a turn earns one royal favour. If there is a tie, the player who built first wins the favour. == 7. THE BAILIFF ADVANCES == If the Provost is on top of or behind the Bailiff, advance the Bailiff one space. If the Provost is ahead of the Bailiff, advance the Bailiff two spaces. The Provost is then placed atop the Bailiff again. == 8. STAGES OF THE CASTLE == If the Bailiff now rests on or past one of the three section markers on the road (Dungeon, Walls, Towers), players earn favours or lose VPs as follows: Dungeon: no house = -2 VPs; 2+ houses = 1 favour Walls: no house = -3 VPs; 2 houses = 1 favour; 3/4 houses = 2 favours; 5+ houses = 3 favours Towers: no house = -4 VPs; 2/3 houses = 1 favour; 4/5 houses = 2 favours; 6+ houses = 3 favours If the Tower section marker is reached, the game is over and final scoring occurs; otherwise, a new turn begins (Step 1). == FINAL SCORING == Gain 3 VPs per gold cube, 1 VP per 3 cubes of the other 4 resource types, and 1 VP per 4 deniers. == ROYAL FAVOURS == There are 4 tracks, which award VPs, deniers, resources or the ability to construct buildings at a discount. Each time you gain a favour, you may advance one space on one track, or select a lower favour if you prefer. Only the first 2 spaces are available initially; once the Dungeon is built the first 4 spaces become available; once the Walls are built the 5th space is available. If multiple favours are gained at once, they must all be taken from different tracks; thus you may only gain 4 favours at once. (E.g. if you build the Monument with the construction favour, you may not use the favour earned from it for construction.) The construction favours may be invoked even if there is no Mason, Lawyer or Architect on the board, or if they are occupied by a worker. 8a953a46a47be7cb7e4779725aba545d0a81ac5b Gamehelpcaylus 0 37 2053 2052 2016-11-15T21:39:20Z Nandblock 11082 /* ACTIVATE PLACES BEFORE THE BRIDGE */ wikitext text/x-wiki == 1: INCOME == Each player receives 2 deniers, plus 1 denier per residence owned, 1 denier if they own the Library, and 2 deniers if they own the Hotel. == 2: PLACE WORKERS == Players in turn either place a worker or pass, in the order dictated by the turn order track, until everyone has passed. Placement may be on any unoccupied place or building on the board. If it is a building owned by another player, that player receives 1 VP. If it is your own building, or if you have a worker in the Inn's rightmost spot, pay 1 denier. Otherwise, pay the lowest unoccupied number on the bridge. [EXCEPTION: in 2-player Caylus, pay 3 deniers, not 2, once the other player passes.] Payments go to the bank, not other players. Passing: place a marker on the lowest number on the Bridge. If you are first to pass, gain 1 denier. == 3: ACTIVATE PLACES BEFORE THE BRIDGE == Beginning with the Gate, any place with a worker is activated, and the worker returns to the player. GATE: Move the worker to any unoccupied place on the board for free. If it is a building owned by another player, they earn 1 VP. TRADING POST: Gain 3 deniers. MERCHANTS' GUILD: Move the provost up to 3 squares forward or back, for free. JOUSTING FIELD: Pay 1 denier + 1 cloth to earn a royal favour. STABLES: Move your marker to the indicated number in the turn order track; all players not in the Stables move down the turn order accordingly. INN: If your worker is on the left spot, move it to the right spot and return any worker there to its owner. If you are in the right spot, you can either leave your worker there or reclaim it. == 4: THE BRIDGE == In order of passing, from first to last, players may move the Provost forward or back, for one denier per square, to a maximum of 3 squares. == 5. ACTIVATE BUILDINGS == Past the bridge, in order, buildings with workers are activated, and the worker is returned to the player. Workers on buildings beyond the Provost are returned without activating those buildings. Notes on some buildings: Production: The 3 stone production buildings when activated by another player also grant one resource to the owner, chosen from the options in brackets. Construction: The Carpenter allows you to construct wood buildings; the Mason, stone buildings. The Lawyer changes a neutral building or one you own into a residence, for 1 denier + 1 cloth. (You cannot transform the Lawyer or a prestige building.) The Architect permits you to construct a prestige building over one of your residences. Constructing a building requires the resources listed on its card. (A white cube = any resource.) When a building is constructed, score the VPs indicated in its top right corner (residences are always 2 VPs). Some buildings also grant a royal favour (Church, Statue, etc.); the Monument grants 2 royal favours. If you build over a building with a worker on it, the transformation is postponed until after the worker's action. == 6. BUILD THE CASTLE == In the order that workers were placed in the castle, each player builds as many units as they like. A unit costs 3 different resources, of which one must be food. If you have a worker in the castle but do not construct a unit, lose 2 VPs. Each unit is worth VPs as follows: 5 VPs for the Dungeon, 4 VPs for the Walls, 3 VPs for the Towers. Each section is built in order (Dungeon, Walls, Towers). After a section marker is passed on the road, work continues in the next section even if the previous one is incomplete. If a section is filled, work immediately commences on the next section. The player who constructs the most units in a turn earns one royal favour. If there is a tie, the player who built first wins the favour. == 7. THE BAILIFF ADVANCES == If the Provost is on top of or behind the Bailiff, advance the Bailiff one space. If the Provost is ahead of the Bailiff, advance the Bailiff two spaces. The Provost is then placed atop the Bailiff again. == 8. STAGES OF THE CASTLE == If the Bailiff now rests on or past one of the three section markers on the road (Dungeon, Walls, Towers), players earn favours or lose VPs as follows: Dungeon: no house = -2 VPs; 2+ houses = 1 favour Walls: no house = -3 VPs; 2 houses = 1 favour; 3/4 houses = 2 favours; 5+ houses = 3 favours Towers: no house = -4 VPs; 2/3 houses = 1 favour; 4/5 houses = 2 favours; 6+ houses = 3 favours If the Tower section marker is reached, the game is over and final scoring occurs; otherwise, a new turn begins (Step 1). == FINAL SCORING == Gain 3 VPs per gold cube, 1 VP per 3 cubes of the other 4 resource types, and 1 VP per 4 deniers. == ROYAL FAVOURS == There are 4 tracks, which award VPs, deniers, resources or the ability to construct buildings at a discount. Each time you gain a favour, you may advance one space on one track, or select a lower favour if you prefer. Only the first 2 spaces are available initially; once the Dungeon is built the first 4 spaces become available; once the Walls are built the 5th space is available. If multiple favours are gained at once, they must all be taken from different tracks; thus you may only gain 4 favours at once. (E.g. if you build the Monument with the construction favour, you may not use the favour earned from it for construction.) The construction favours may be invoked even if there is no Mason, Lawyer or Architect on the board, or if they are occupied by a worker. a8ea829c0f91de7fc9c697d426010f1fe6a65632 2054 2053 2016-11-15T21:39:30Z Nandblock 11082 /* 7. THE BAILIFF ADVANCES */ wikitext text/x-wiki == 1: INCOME == Each player receives 2 deniers, plus 1 denier per residence owned, 1 denier if they own the Library, and 2 deniers if they own the Hotel. == 2: PLACE WORKERS == Players in turn either place a worker or pass, in the order dictated by the turn order track, until everyone has passed. Placement may be on any unoccupied place or building on the board. If it is a building owned by another player, that player receives 1 VP. If it is your own building, or if you have a worker in the Inn's rightmost spot, pay 1 denier. Otherwise, pay the lowest unoccupied number on the bridge. [EXCEPTION: in 2-player Caylus, pay 3 deniers, not 2, once the other player passes.] Payments go to the bank, not other players. Passing: place a marker on the lowest number on the Bridge. If you are first to pass, gain 1 denier. == 3: ACTIVATE PLACES BEFORE THE BRIDGE == Beginning with the Gate, any place with a worker is activated, and the worker returns to the player. GATE: Move the worker to any unoccupied place on the board for free. If it is a building owned by another player, they earn 1 VP. TRADING POST: Gain 3 deniers. MERCHANTS' GUILD: Move the provost up to 3 squares forward or back, for free. JOUSTING FIELD: Pay 1 denier + 1 cloth to earn a royal favour. STABLES: Move your marker to the indicated number in the turn order track; all players not in the Stables move down the turn order accordingly. INN: If your worker is on the left spot, move it to the right spot and return any worker there to its owner. If you are in the right spot, you can either leave your worker there or reclaim it. == 4: THE BRIDGE == In order of passing, from first to last, players may move the Provost forward or back, for one denier per square, to a maximum of 3 squares. == 5. ACTIVATE BUILDINGS == Past the bridge, in order, buildings with workers are activated, and the worker is returned to the player. Workers on buildings beyond the Provost are returned without activating those buildings. Notes on some buildings: Production: The 3 stone production buildings when activated by another player also grant one resource to the owner, chosen from the options in brackets. Construction: The Carpenter allows you to construct wood buildings; the Mason, stone buildings. The Lawyer changes a neutral building or one you own into a residence, for 1 denier + 1 cloth. (You cannot transform the Lawyer or a prestige building.) The Architect permits you to construct a prestige building over one of your residences. Constructing a building requires the resources listed on its card. (A white cube = any resource.) When a building is constructed, score the VPs indicated in its top right corner (residences are always 2 VPs). Some buildings also grant a royal favour (Church, Statue, etc.); the Monument grants 2 royal favours. If you build over a building with a worker on it, the transformation is postponed until after the worker's action. == 6. BUILD THE CASTLE == In the order that workers were placed in the castle, each player builds as many units as they like. A unit costs 3 different resources, of which one must be food. If you have a worker in the castle but do not construct a unit, lose 2 VPs. Each unit is worth VPs as follows: 5 VPs for the Dungeon, 4 VPs for the Walls, 3 VPs for the Towers. Each section is built in order (Dungeon, Walls, Towers). After a section marker is passed on the road, work continues in the next section even if the previous one is incomplete. If a section is filled, work immediately commences on the next section. The player who constructs the most units in a turn earns one royal favour. If there is a tie, the player who built first wins the favour. == 7. THE BAILIFF ADVANCES == If the Provost is on top of or behind the Bailiff, advance the Bailiff one space. If the Provost is ahead of the Bailiff, advance the Bailiff two spaces. The Provost is then placed atop the Bailiff again. == 8. STAGES OF THE CASTLE == If the Bailiff now rests on or past one of the three section markers on the road (Dungeon, Walls, Towers), players earn favours or lose VPs as follows: Dungeon: no house = -2 VPs; 2+ houses = 1 favour Walls: no house = -3 VPs; 2 houses = 1 favour; 3/4 houses = 2 favours; 5+ houses = 3 favours Towers: no house = -4 VPs; 2/3 houses = 1 favour; 4/5 houses = 2 favours; 6+ houses = 3 favours If the Tower section marker is reached, the game is over and final scoring occurs; otherwise, a new turn begins (Step 1). == FINAL SCORING == Gain 3 VPs per gold cube, 1 VP per 3 cubes of the other 4 resource types, and 1 VP per 4 deniers. == ROYAL FAVOURS == There are 4 tracks, which award VPs, deniers, resources or the ability to construct buildings at a discount. Each time you gain a favour, you may advance one space on one track, or select a lower favour if you prefer. Only the first 2 spaces are available initially; once the Dungeon is built the first 4 spaces become available; once the Walls are built the 5th space is available. If multiple favours are gained at once, they must all be taken from different tracks; thus you may only gain 4 favours at once. (E.g. if you build the Monument with the construction favour, you may not use the favour earned from it for construction.) The construction favours may be invoked even if there is no Mason, Lawyer or Architect on the board, or if they are occupied by a worker. 19de3e9cc254fa6c3bc7ed1fdf45a0d92adcf934 2055 2054 2016-11-15T21:39:39Z Nandblock 11082 /* FINAL SCORING */ wikitext text/x-wiki == 1: INCOME == Each player receives 2 deniers, plus 1 denier per residence owned, 1 denier if they own the Library, and 2 deniers if they own the Hotel. == 2: PLACE WORKERS == Players in turn either place a worker or pass, in the order dictated by the turn order track, until everyone has passed. Placement may be on any unoccupied place or building on the board. If it is a building owned by another player, that player receives 1 VP. If it is your own building, or if you have a worker in the Inn's rightmost spot, pay 1 denier. Otherwise, pay the lowest unoccupied number on the bridge. [EXCEPTION: in 2-player Caylus, pay 3 deniers, not 2, once the other player passes.] Payments go to the bank, not other players. Passing: place a marker on the lowest number on the Bridge. If you are first to pass, gain 1 denier. == 3: ACTIVATE PLACES BEFORE THE BRIDGE == Beginning with the Gate, any place with a worker is activated, and the worker returns to the player. GATE: Move the worker to any unoccupied place on the board for free. If it is a building owned by another player, they earn 1 VP. TRADING POST: Gain 3 deniers. MERCHANTS' GUILD: Move the provost up to 3 squares forward or back, for free. JOUSTING FIELD: Pay 1 denier + 1 cloth to earn a royal favour. STABLES: Move your marker to the indicated number in the turn order track; all players not in the Stables move down the turn order accordingly. INN: If your worker is on the left spot, move it to the right spot and return any worker there to its owner. If you are in the right spot, you can either leave your worker there or reclaim it. == 4: THE BRIDGE == In order of passing, from first to last, players may move the Provost forward or back, for one denier per square, to a maximum of 3 squares. == 5. ACTIVATE BUILDINGS == Past the bridge, in order, buildings with workers are activated, and the worker is returned to the player. Workers on buildings beyond the Provost are returned without activating those buildings. Notes on some buildings: Production: The 3 stone production buildings when activated by another player also grant one resource to the owner, chosen from the options in brackets. Construction: The Carpenter allows you to construct wood buildings; the Mason, stone buildings. The Lawyer changes a neutral building or one you own into a residence, for 1 denier + 1 cloth. (You cannot transform the Lawyer or a prestige building.) The Architect permits you to construct a prestige building over one of your residences. Constructing a building requires the resources listed on its card. (A white cube = any resource.) When a building is constructed, score the VPs indicated in its top right corner (residences are always 2 VPs). Some buildings also grant a royal favour (Church, Statue, etc.); the Monument grants 2 royal favours. If you build over a building with a worker on it, the transformation is postponed until after the worker's action. == 6. BUILD THE CASTLE == In the order that workers were placed in the castle, each player builds as many units as they like. A unit costs 3 different resources, of which one must be food. If you have a worker in the castle but do not construct a unit, lose 2 VPs. Each unit is worth VPs as follows: 5 VPs for the Dungeon, 4 VPs for the Walls, 3 VPs for the Towers. Each section is built in order (Dungeon, Walls, Towers). After a section marker is passed on the road, work continues in the next section even if the previous one is incomplete. If a section is filled, work immediately commences on the next section. The player who constructs the most units in a turn earns one royal favour. If there is a tie, the player who built first wins the favour. == 7. THE BAILIFF ADVANCES == If the Provost is on top of or behind the Bailiff, advance the Bailiff one space. If the Provost is ahead of the Bailiff, advance the Bailiff two spaces. The Provost is then placed atop the Bailiff again. == 8. STAGES OF THE CASTLE == If the Bailiff now rests on or past one of the three section markers on the road (Dungeon, Walls, Towers), players earn favours or lose VPs as follows: Dungeon: no house = -2 VPs; 2+ houses = 1 favour Walls: no house = -3 VPs; 2 houses = 1 favour; 3/4 houses = 2 favours; 5+ houses = 3 favours Towers: no house = -4 VPs; 2/3 houses = 1 favour; 4/5 houses = 2 favours; 6+ houses = 3 favours If the Tower section marker is reached, the game is over and final scoring occurs; otherwise, a new turn begins (Step 1). == FINAL SCORING == Gain 3 VPs per gold cube, 1 VP per 3 cubes of the other 4 resource types, and 1 VP per 4 deniers. == ROYAL FAVOURS == There are 4 tracks, which award VPs, deniers, resources or the ability to construct buildings at a discount. Each time you gain a favour, you may advance one space on one track, or select a lower favour if you prefer. Only the first 2 spaces are available initially; once the Dungeon is built the first 4 spaces become available; once the Walls are built the 5th space is available. If multiple favours are gained at once, they must all be taken from different tracks; thus you may only gain 4 favours at once. (E.g. if you build the Monument with the construction favour, you may not use the favour earned from it for construction.) The construction favours may be invoked even if there is no Mason, Lawyer or Architect on the board, or if they are occupied by a worker. 5f3eb671634c339c8e5dcf6a18a03e649594b196 2056 2055 2016-11-15T21:41:10Z Nandblock 11082 /* FINAL SCORING */ wikitext text/x-wiki == 1: INCOME == Each player receives 2 deniers, plus 1 denier per residence owned, 1 denier if they own the Library, and 2 deniers if they own the Hotel. == 2: PLACE WORKERS == Players in turn either place a worker or pass, in the order dictated by the turn order track, until everyone has passed. Placement may be on any unoccupied place or building on the board. If it is a building owned by another player, that player receives 1 VP. If it is your own building, or if you have a worker in the Inn's rightmost spot, pay 1 denier. Otherwise, pay the lowest unoccupied number on the bridge. [EXCEPTION: in 2-player Caylus, pay 3 deniers, not 2, once the other player passes.] Payments go to the bank, not other players. Passing: place a marker on the lowest number on the Bridge. If you are first to pass, gain 1 denier. == 3: ACTIVATE PLACES BEFORE THE BRIDGE == Beginning with the Gate, any place with a worker is activated, and the worker returns to the player. GATE: Move the worker to any unoccupied place on the board for free. If it is a building owned by another player, they earn 1 VP. TRADING POST: Gain 3 deniers. MERCHANTS' GUILD: Move the provost up to 3 squares forward or back, for free. JOUSTING FIELD: Pay 1 denier + 1 cloth to earn a royal favour. STABLES: Move your marker to the indicated number in the turn order track; all players not in the Stables move down the turn order accordingly. INN: If your worker is on the left spot, move it to the right spot and return any worker there to its owner. If you are in the right spot, you can either leave your worker there or reclaim it. == 4: THE BRIDGE == In order of passing, from first to last, players may move the Provost forward or back, for one denier per square, to a maximum of 3 squares. == 5. ACTIVATE BUILDINGS == Past the bridge, in order, buildings with workers are activated, and the worker is returned to the player. Workers on buildings beyond the Provost are returned without activating those buildings. Notes on some buildings: Production: The 3 stone production buildings when activated by another player also grant one resource to the owner, chosen from the options in brackets. Construction: The Carpenter allows you to construct wood buildings; the Mason, stone buildings. The Lawyer changes a neutral building or one you own into a residence, for 1 denier + 1 cloth. (You cannot transform the Lawyer or a prestige building.) The Architect permits you to construct a prestige building over one of your residences. Constructing a building requires the resources listed on its card. (A white cube = any resource.) When a building is constructed, score the VPs indicated in its top right corner (residences are always 2 VPs). Some buildings also grant a royal favour (Church, Statue, etc.); the Monument grants 2 royal favours. If you build over a building with a worker on it, the transformation is postponed until after the worker's action. == 6. BUILD THE CASTLE == In the order that workers were placed in the castle, each player builds as many units as they like. A unit costs 3 different resources, of which one must be food. If you have a worker in the castle but do not construct a unit, lose 2 VPs. Each unit is worth VPs as follows: 5 VPs for the Dungeon, 4 VPs for the Walls, 3 VPs for the Towers. Each section is built in order (Dungeon, Walls, Towers). After a section marker is passed on the road, work continues in the next section even if the previous one is incomplete. If a section is filled, work immediately commences on the next section. The player who constructs the most units in a turn earns one royal favour. If there is a tie, the player who built first wins the favour. == 7. THE BAILIFF ADVANCES == If the Provost is on top of or behind the Bailiff, advance the Bailiff one space. If the Provost is ahead of the Bailiff, advance the Bailiff two spaces. The Provost is then placed atop the Bailiff again. == 8. STAGES OF THE CASTLE == If the Bailiff now rests on or past one of the three section markers on the road (Dungeon, Walls, Towers), players earn favours or lose VPs as follows: Dungeon: no house = -2 VPs; 2+ houses = 1 favour Walls: no house = -3 VPs; 2 houses = 1 favour; 3/4 houses = 2 favours; 5+ houses = 3 favours Towers: no house = -4 VPs; 2/3 houses = 1 favour; 4/5 houses = 2 favours; 6+ houses = 3 favours If the Tower section marker is reached, the game is over and final scoring occurs; otherwise, a new turn begins (Step 1). == FINAL SCORING == In addition to the VPs gained during the game, gain 3 VPs per gold cube, 1 VP per 3 cubes of the other 4 resource types, and 1 VP per 4 deniers. == ROYAL FAVOURS == There are 4 tracks, which award VPs, deniers, resources or the ability to construct buildings at a discount. Each time you gain a favour, you may advance one space on one track, or select a lower favour if you prefer. Only the first 2 spaces are available initially; once the Dungeon is built the first 4 spaces become available; once the Walls are built the 5th space is available. If multiple favours are gained at once, they must all be taken from different tracks; thus you may only gain 4 favours at once. (E.g. if you build the Monument with the construction favour, you may not use the favour earned from it for construction.) The construction favours may be invoked even if there is no Mason, Lawyer or Architect on the board, or if they are occupied by a worker. e0df3dc21a702ae65eb91ba64cf7692a63226fd6 2058 2056 2016-11-15T22:33:37Z Nandblock 11082 wikitext text/x-wiki == ROUNDS == Each round consists of seven phases, with an eighth (awarding favours for constructing the castle) that occurs at 3 designated points in the game. == 1: INCOME == Each player receives 2 deniers, plus 1 denier per residence owned, 1 denier if they own the Library, and 2 deniers if they own the Hotel. == 2: PLACE WORKERS == Players in turn either place a worker or pass, in the order dictated by the turn order track, until everyone has passed. Placement may be on any unoccupied place or building on the board. If it is a building owned by another player, that player receives 1 VP. If it is your own building, or if you have a worker in the Inn's rightmost spot, pay 1 denier. Otherwise, pay the lowest unoccupied number on the bridge. [EXCEPTION: in 2-player Caylus, pay 3 deniers, not 2, once the other player passes.] Payments go to the bank, not other players. Passing: place a marker on the lowest number on the Bridge. If you are first to pass, gain 1 denier. == 3: ACTIVATE PLACES BEFORE THE BRIDGE == Beginning with the Gate, any place with a worker is activated, and the worker returns to the player. '''GATE:''' Move the worker to any unoccupied place on the board for free. If it is a building owned by another player, they earn 1 VP. '''TRADING POST:''' Gain 3 deniers. '''MERCHANTS' GUILD:''' Move the provost up to 3 squares forward or back, for free. '''JOUSTING FIELD:''' Pay 1 denier + 1 cloth to earn a royal favour. '''STABLES:''' Move your marker to the indicated number in the turn order track; all players not in the Stables move down the turn order accordingly. '''INN:''' If your worker is on the left spot, move it to the right spot and return any worker there to its owner. If you are in the right spot, you can either leave your worker there or reclaim it. (The effects of this spot are only available in phase 2, above.) == 4: THE BRIDGE == In order of passing, from first to last, players may move the Provost forward or back, for one denier per square, to a maximum of 3 squares. == 5. ACTIVATE BUILDINGS == Past the bridge, in order, buildings with workers are activated, and the worker is returned to the player. Workers on buildings beyond the Provost are returned without activating those buildings. Notes on some buildings: '''Production:''' The 3 stone production buildings when activated by another player also grant one resource to the owner, chosen from the options in brackets. '''Construction:''' The Carpenter allows you to construct wood buildings; the Mason, stone buildings. The Lawyer changes a neutral building or one you own into a residence, for 1 denier + 1 cloth. (You cannot transform the Lawyer or a prestige building.) The Architect permits you to construct a prestige building over one of your residences. Constructing a building requires the resources listed on its card. (A white cube = any resource.) When a building is constructed, score the VPs indicated in its top right corner (residences are always 2 VPs). Some buildings also grant a royal favour (Church, Statue, etc.); the Monument grants 2 royal favours. If you build over a building with a worker on it, the transformation is postponed until after the worker's action. == 6. BUILD THE CASTLE == In the order that workers were placed in the castle, each player builds as many units as they like. A unit costs 3 different resources, of which one must be food. If you have a worker in the castle but do not construct a unit, lose 2 VPs. Each unit is worth VPs as follows: 5 VPs for the Dungeon, 4 VPs for the Walls, 3 VPs for the Towers. Each section is built in order (Dungeon, Walls, Towers). After a section marker is passed on the road, work continues in the next section even if the previous one is incomplete. If a section is filled, work immediately commences on the next section. The player who constructs the most units in a turn earns one royal favour. If there is a tie, the player who built first wins the favour. == 7. THE BAILIFF ADVANCES == If the Provost is on top of or behind the Bailiff, advance the Bailiff one space. If the Provost is ahead of the Bailiff, advance the Bailiff two spaces. The Provost is then placed atop the Bailiff again. == 8. STAGES OF THE CASTLE == If the Bailiff now rests on or past one of the three section markers on the road (Dungeon, Walls, Towers), players earn favours or lose VPs as follows: '''Dungeon:''' no house = -2 VPs; 2+ houses = 1 favour '''Walls:''' no house = -3 VPs; 2 houses = 1 favour; 3/4 houses = 2 favours; 5+ houses = 3 favours '''Towers:''' no house = -4 VPs; 2/3 houses = 1 favour; 4/5 houses = 2 favours; 6+ houses = 3 favours If the Tower section marker is reached, or if the Towers are fully constructed already, the game is over and final scoring occurs; otherwise, a new turn begins (Step 1). == FINAL SCORING == In addition to the VPs gained during the game, gain 3 VPs per gold cube, 1 VP per 3 cubes of the other 4 resource types, and 1 VP per 4 deniers. == ROYAL FAVOURS == There are 4 tracks, which award VPs, deniers, resources or the ability to construct buildings at a discount. Each time you gain a favour, you may advance one space on one track, or select a lower favour if you prefer. Only the first 2 spaces are available initially; once the Dungeon is built the first 4 spaces become available; once the Walls are built the 5th space is available. If multiple favours are gained at once, they must all be taken from different tracks; thus you may only gain 4 favours at once. (E.g. if you build the Monument with the construction favour, you may not use the favour earned from it for construction.) The construction favours may be invoked even if there is no Mason, Lawyer or Architect on the board, or if they are occupied by a worker. 855e976673665caf1c6c05640a9531698e442953 2059 2058 2016-11-15T22:35:56Z Nandblock 11082 wikitext text/x-wiki == ROUNDS == Each round consists of seven phases, with an eighth (awarding favours for constructing the castle) that occurs at 3 designated points in the game. == 1: INCOME == Each player receives 2 deniers, plus 1 denier per residence owned, 1 denier if they own the Library, and 2 deniers if they own the Hotel. == 2: PLACE WORKERS == Players in turn either place a worker or pass, in the order dictated by the turn order track, until everyone has passed. Placement may be on any unoccupied place or building on the board. If it is a building owned by another player, that player receives 1 VP. If it is your own building, or if you have a worker in the Inn's rightmost spot, pay 1 denier. Otherwise, pay the lowest unoccupied number on the bridge. [EXCEPTION: in 2-player Caylus, pay 3 deniers, not 2, once the other player passes.] Payments go to the bank, not other players. Passing: place a marker on the lowest number on the Bridge. If you are first to pass, gain 1 denier. == 3: ACTIVATE PLACES BEFORE THE BRIDGE == Beginning with the Gate, any place with a worker is activated, and the worker returns to the player. '''GATE:''' Move the worker to any unoccupied place on the board for free. If it is a building owned by another player, they earn 1 VP. '''TRADING POST:''' Gain 3 deniers. '''MERCHANTS' GUILD:''' Move the provost up to 3 squares forward or back, for free. '''JOUSTING FIELD:''' Pay 1 denier + 1 cloth to earn a royal favour. '''STABLES:''' Move your marker to the indicated number in the turn order track; all players not in the Stables move down the turn order accordingly. '''INN:''' If your worker is on the left spot, move it to the right spot and return any worker there to its owner. If you are in the right spot, you can either leave your worker there or reclaim it. (The effects of this spot are only available in phase 2, above.) == 4: THE BRIDGE == In order of passing, from first to last, players may move the Provost forward or back, for one denier per square, to a maximum of 3 squares. == 5. ACTIVATE BUILDINGS == Past the bridge, in order, buildings with workers are activated, and the worker is returned to the player. Workers on buildings beyond the Provost are returned without activating those buildings. Notes on some buildings: '''Production:''' The 3 stone production buildings when activated by another player also grant one resource to the owner, chosen from the options in brackets. '''Construction:''' The Carpenter allows you to construct wood buildings; the Mason, stone buildings. The Lawyer changes a neutral building or one you own into a residence, for 1 denier + 1 cloth. (You cannot transform the Lawyer or a prestige building.) The Architect permits you to construct a prestige building over one of your residences. Constructing a building requires the resources listed on its card. (A white cube = any resource.) When a building is constructed, score the VPs indicated in its top right corner (residences are always 2 VPs). Some buildings also grant a royal favour (Church, Statue, etc.); the Monument grants 2 royal favours. If you build over a building with a worker on it, the transformation is postponed until after the worker's action. == 6. BUILD THE CASTLE == In the order that workers were placed in the castle, each player builds as many units as they like. A unit costs 3 different resources, of which one must be food. If you have a worker in the castle but do not construct a unit, lose 2 VPs. Each unit is worth VPs as follows: 5 VPs for the Dungeon, 4 VPs for the Walls, 3 VPs for the Towers. Each section is built in order (Dungeon, Walls, Towers). After a section marker is passed on the road, work continues in the next section even if the previous one is incomplete. If a section is filled, work immediately commences on the next section. The player who constructs the most units in a turn earns one royal favour. If there is a tie, the player who built first wins the favour. == 7. THE BAILIFF ADVANCES == If the Provost is on top of or behind the Bailiff, advance the Bailiff one space. If the Provost is ahead of the Bailiff, advance the Bailiff two spaces. The Provost is then placed atop the Bailiff again. == 8. STAGES OF THE CASTLE == If the Bailiff now rests on or past one of the three section markers on the road (Dungeon, Walls, Towers), players earn favours or lose VPs as follows: '''Dungeon:''' no house = -2 VPs; 2+ houses = 1 favour '''Walls:''' no house = -3 VPs; 2 houses = 1 favour; 3/4 houses = 2 favours; 5+ houses = 3 favours '''Towers:''' no house = -4 VPs; 2/3 houses = 1 favour; 4/5 houses = 2 favours; 6+ houses = 3 favours If the Tower section marker is reached, or if the Towers are fully constructed already, the game is over and final scoring occurs; otherwise, a new turn begins (Step 1). == FINAL SCORING == In addition to the VPs gained during the game, gain 3 VPs per gold cube, 1 VP per 3 cubes of the other 4 resource types, and 1 VP per 4 deniers. == ROYAL FAVOURS == There are 4 tracks, which award VPs, deniers, resources or the ability to construct buildings at a discount. Each time you gain a favour, you may advance one space on one track, or select a lower favour if you prefer. Only the first 2 spaces are available initially; once the Dungeon is built the first 4 spaces become available; once the Walls are built the 5th space is available. If multiple favours are gained at once, they must all be taken from different tracks; thus you may only gain 4 favours at once. (E.g. if you build the Monument with the construction favour, you may not use the favour earned from it for construction.) The construction favours may be invoked even if there is no Mason, Lawyer or Architect on the board, or if they are occupied by a worker. f457098f1d74a1e6c819e8a4c8634113170720e2 Kaozeal:Gamehelpcaylus 1 240 2057 2016-11-15T21:43:21Z Nandblock 11082 Created page with "Since the Caylus page was empty I put in a condensation of the rules -- please edit it as it's a complex game and I may have missed something important!!!! --nandblock" wikitext text/x-wiki Since the Caylus page was empty I put in a condensation of the rules -- please edit it as it's a complex game and I may have missed something important!!!! --nandblock fc2158929716aea265a368578f01cda5dd4ed752 Gamehelplostcities 0 210 2060 2031 2024-04-03T12:32:57Z Choarier56 15053 wikitext text/x-wiki '''AN DAFAR :''' 60 kartenn, 5 liv (a glot gant an « ergerzhadennoù » war an dachenn c’hoari) 9 kartenn evit pep liv niverennet etre 2 ha 10, mui 3 c'hartenn « pariadenn » evit pep liv. '''C'HOARI :''' D'ho tro, e rankit : 1. Pe : ouzhpennañ ur gartenn d’ur golonenn ergerzhadenn dirazoc'h (unan evit pep liv d'ar muiañ), pe diskargañ unan anezhi e-kreiz ar plato-c’hoari. 2. Kemer ar gartenn gentañ eus ar pigos pe kemer unan bet diskarget e-kreiz (an hini diwezhañ bet diskarget evit pep liv, nemet an hini emaoc'h o paouez diskargañ m'ho peus diskarget unan). Ret eo ober an daou dra-se. '''REOLENNOÙ :''' Ur gartenn c'hoariet e-barzh uann deus ho kolonennoù ergerzhadenn a rank bezañ uheloc’h eget an hini diwezhañ bet lakaet war ar memes kolonenn, met posupl eo laoskel toulloù etre ar sifroù. Evit c'hoari ur gartenn pariadenn (pe meur a hini) eo ret kregiñ ar golonenn gant ar gartenn-mañ. Ur wech lakaet ur gartenn « sifr » eo re ziwezhat. N'eo ket ret kregiñ ar 5 kolonenn ergerzhadenn, n'eus ken nemet ar c'holonennoù kroget hag a vo kemeret e gont evit disoc'h ar c'hoari. Achu eo ar c'hoari pa vez pigoset ar gartenn ziwezhañ e-barzh ar pigos. '''AR POENTOÙ :''' Evit gounit ur bartiad, e vo ret deoc’h rastellat ar muiañ a boentoù war ho kolonennoù ergerzhadennoù. Kontet e vo ar poentoù evel-se evit pep kolonenn ergerzhadenn : 1. Grit sammad an holl gartennoù niverennet er golonenn ergerzhadenn. 2. Tennit 20 poent m'ho peus lakaet ur gartenn e-barzh ar golonenn (ur gartenn gant ur sifr pe unan « pariadenn ») 3. Lieskementit dre (niver a gartennoù pariadennoù + 1) 4. Ouzhpennit 20 poent bonus ma vez 8 kartenn (pe muioc'h) e-barzh an ergerzhadenn (kartennoù pariadennoù e-barzh) ''Da lâret eo, ur golonenn ergerzhadenn kroget gant ur gartenn pariadenn hepken a lakao ac'hanoc'h da goll 40 poent : (0 - 20) * (1 +1)'' 863d0f947b310068f99c71a71abf5fb239222459 ServiceOutage 0 241 2061 2024-07-10T12:01:51Z Choarier56 15053 Troet e brezhoneg wikitext text/x-wiki === Hor sav-poent === N'eo ket aes kinnig ur servij c'hoari enlinenn pemdeziek, a-hed ar sizhun, evit ur skipailh (bihan-tre) evel hon hini. Ouzhpenn-se, ur servij en amzer real eo BGA, ha pep kudenn a c'hellfe diskar ar partiennoù o ren. Hor sav-poent eo bezañ sklaer ha treuzwelus war ar pezh a c'hoarvez, displegañ perak eo c'hoarvezet, peseurt koñsekañsoù (hag e-pad pegeit), ha petra hon eus graet evit ma ne c'hoarvezfe ket en-dro. Displegañ deoc'h kement-se eo pal ar bajenn-mañ. Notenn : Ma c'hoarvez ur gwallzarvoud e vo embannet titouroù war-eeun war twitter [[/twitter.com/boardgamearena|https://twitter.com/boardgamearena]] ha/pe war hor pajenn Facebook [[/www.facebook.com/boardgamearena/|https://www.facebook.com/boardgamearena/]]. 019d3c794c241e136fc827858dd1e5d1b6f76eb8